#include <iostream> #include <vector> #include <map> #include <random> using namespace std; typedef long long ll; const ll MOD_A = 1000000000000000003LL; // Large prime for modulo operation const ll MOD_B = 1000000000000000031LL; // Another large prime int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N, Q; cin >> N >> Q; // Generate random coefficients a and b for each element vector<ll> a(N), b(N); random_device rd; mt19937_64 gen(rd()); uniform_int_distribution<ll> dis_a(1, MOD_A - 1); uniform_int_distribution<ll> dis_b(1, MOD_B - 1); for (int i = 0; i < N; ++i) { a[i] = dis_a(gen); b[i] = dis_b(gen); } // Compute prefix sums for a and b vector<ll> prefix_a(N + 1, 0), prefix_b(N + 1, 0); for (int i = 0; i < N; ++i) { prefix_a[i + 1] = prefix_a[i] + a[i]; prefix_b[i + 1] = prefix_b[i] + b[i]; } // Current hash values ll current_hash_a = 0, current_hash_b = 0; map<pair<ll, ll>, int> hash_map; hash_map[{0, 0}] = 0; // Initial state after 0 queries for (int q = 1; q <= Q; ++q) { string type; cin >> type; if (type == "!") { int L, R, K; cin >> L >> R >> K; // Calculate sum_a and sum_b for the interval [L, R) ll sum_a = prefix_a[R] - prefix_a[L]; ll sum_b = prefix_b[R] - prefix_b[L]; // Apply modulo to handle negative values ll sum_a_mod = (sum_a % MOD_A + MOD_A) % MOD_A; ll sum_b_mod = (sum_b % MOD_B + MOD_B) % MOD_B; ll delta_a = (sum_a_mod * K) % MOD_A; current_hash_a = (current_hash_a + delta_a) % MOD_A; ll delta_b = (sum_b_mod * K) % MOD_B; current_hash_b = (current_hash_b + delta_b) % MOD_B; // Ensure non-negative current_hash_a = (current_hash_a + MOD_A) % MOD_A; current_hash_b = (current_hash_b + MOD_B) % MOD_B; pair<ll, ll> current_hash = {current_hash_a, current_hash_b}; if (hash_map.find(current_hash) == hash_map.end()) { hash_map[current_hash] = q; } } else if (type == "?") { pair<ll, ll> current_hash = {current_hash_a, current_hash_b}; auto it = hash_map.find(current_hash); if (it != hash_map.end()) { cout << it->second << '\n'; } else { // This case should not occur as per the problem constraints cout << 0 << '\n'; } } } return 0; }