#include #include #define rep(i,n) for(int i=0;i P; template ostream& operator<<(ostream& os, const static_modint& a) {os << a.val(); return os;} template ostream& operator<<(ostream& os, const dynamic_modint& a) {os << a.val(); return os;} template istream& operator>>(istream& is, static_modint& a) {long long x; is >> x; a = x; return is;} template istream& operator>>(istream& is, dynamic_modint& a) {long long x; is >> x; a = x; return is;} template istream& operator>>(istream& is, vector& v){int n = v.size(); assert(n > 0); rep(i, n) is >> v[i]; return is;} template ostream& operator<<(ostream& os, const pair& p){os << p.first << ' ' << p.second; return os;} template ostream& operator<<(ostream& os, const vector& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : " "); return os;} template ostream& operator<<(ostream& os, const vector>& v){int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "\n" : ""); return os;} template ostream& operator<<(ostream& os, const set& se){for(T x : se) os << x << " "; os << "\n"; return os;} template ostream& operator<<(ostream& os, const multiset& se){for(T x : se) os << x << " "; os << "\n"; return os;} template ostream& operator<<(ostream& os, const unordered_set& se){for(T x : se) os << x << " "; os << "\n"; return os;} template ostream& operator<<(ostream& os, const atcoder::segtree& seg){int n = seg.max_right(0, [](S){return true;}); rep(i, n) os << seg.get(i) << (i == n - 1 ? "\n" : " "); return os;} template ostream& operator<<(ostream& os, const atcoder::lazy_segtree& seg){int n = seg.max_right(0, [](S){return true;}); rep(i, n) os << seg.get(i) << (i == n - 1 ? "\n" : " "); return os;} template void chmin(T& a, T b){a = min(a, b);} template void chmax(T& a, T b){a = max(a, b);} // Mo's algorithm for q queries(Ranges [l, r] should be 0-indexed!) // T is the typename of Answers template struct Mo{ int n; vector a; int q; vector l, r; vector qs; vector ans; int Ma = 500005; Mo(int _n, vector _a, int _q, vector _l, vector _r) : n(_n), a(_a), q(_q), l(_l), r(_r), qs(_q), ans(_q) { assert(int(a.size()) == n); assert(int(l.size()) == q); assert(int(r.size()) == q); rep(i, q) r[i]++; rep(i, q) qs[i] = i; int D = n / (sqrt(q) + 1) + 1; sort(qs.begin(), qs.end(), [&](int i, int j){ int di = r[i] / D, dj = r[j] / D; if(di == dj) return l[i] < l[j]; return r[i] < r[j]; }); rep(i, n) Ma = max(Ma, a[i] + 5); } vector solve(){ int li = 0, ri = 0; T now = 0; vector cnt(Ma); auto calc = [&](int x){ T res = x / 2; return res; }; auto add = [&](int i){ now -= calc(cnt[a[i]]); cnt[a[i]]++; now += calc(cnt[a[i]]); }; auto del = [&](int i){ now -= calc(cnt[a[i]]); cnt[a[i]]--; now += calc(cnt[a[i]]); }; for(int qi : qs){ int nl = l[qi], nr = r[qi]; while(ri < nr) add(ri), ri++; while(li > nl) li--, add(li); while(ri > nr) ri--, del(ri); while(li < nl) del(li), li++; ans[qi] = now; } return ans; } }; int main(){ int N, Q; cin >> N >> Q; vector A(N); cin >> A; vector> ChangeQuery; vector> AnswerQuery; int ChangeCount = 0; int AnswerCount = 0; { vector A_copy = A; rep(i, Q){ int t; cin >> t; if(t == 1){ int i, x; cin >> i >> x; i--; ChangeQuery.emplace_back(i, A_copy[i], x); A_copy[i] = x; ChangeCount++; } if(t == 2){ int r; cin >> r; AnswerQuery.emplace_back(r, ChangeCount); AnswerCount++; } } } vector AnswerSort(AnswerCount); rep(i, AnswerCount) AnswerSort[i] = i; // int D = sqrt(N + AnswerCount); int D = 500; sort(AnswerSort.begin(), AnswerSort.end(), [&](int i, int j){ auto [xi, yi] = AnswerQuery[i]; auto [xj, yj] = AnswerQuery[j]; int di = yi / D, dj = yj / D; if(di == dj) return xi < xj; return yi < yj; }); multiset alpha; multiset beta; auto add = [&](int val){ auto right = alpha.upper_bound(val); auto left = prev(right); if(right != alpha.begin() and right != alpha.end()){ beta.erase(beta.find(*right xor *left)); } if(right != alpha.begin()){ beta.insert(val xor *left); } if(right != alpha.end()){ beta.insert(val xor *right); } alpha.insert(val); }; auto del = [&](int val){ auto itr = alpha.find(val); auto left = prev(itr); auto right = next(itr); if(itr != alpha.begin()){ beta.erase(beta.find(val xor *left)); } if(right != alpha.end()){ beta.erase(beta.find(val xor *right)); } if(itr != alpha.begin() and right != alpha.end()){ beta.insert(*left xor *right); } alpha.erase(itr); }; vector Ans(AnswerCount); { int x = 2, y = 0; alpha.insert(A[0]); alpha.insert(A[1]); beta.insert(A[0] xor A[1]); auto right = [&](){ add(A[x]); x++; }; auto left = [&](){ x--; del(A[x]); }; auto up = [&](){ auto [i, from, to] = ChangeQuery[y]; if(i < x) del(A[i]); A[i] = to; if(i < x) add(A[i]); y++; }; auto down = [&](){ y--; auto [i, from, to] = ChangeQuery[y]; if(i < x) del(A[i]); A[i] = from; if(i < x) add(A[i]); }; for(int qi : AnswerSort){ auto [x_goal, y_goal] = AnswerQuery[qi]; while(x < x_goal) right(); while(y > y_goal) down(); while(x > x_goal) left(); while(y < y_goal) up(); Ans[qi] = *beta.begin(); /* cerr << x << ' ' << y << "\n"; cerr << alpha; cerr << beta; cerr<< "--------\n"; */ } } for(auto x : Ans){ cout << x << "\n"; } return 0; }