#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using Int = long long; template ostream &operator<<(ostream &os, const pair &a) { return os << "(" << a.first << ", " << a.second << ")"; }; template ostream &operator<<(ostream &os, const vector &as) { const int sz = as.size(); os << "["; for (int i = 0; i < sz; ++i) { if (i >= 256) { os << ", ..."; break; } if (i > 0) { os << ", "; } os << as[i]; } return os << "]"; } template void pv(T a, T b) { for (T i = a; i != b; ++i) cerr << *i << " "; cerr << endl; } template bool chmin(T &t, const T &f) { if (t > f) { t = f; return true; } return false; } template bool chmax(T &t, const T &f) { if (t < f) { t = f; return true; } return false; } #define COLOR(s) ("\x1b[" s "m") // cannot use count // no move constructor (==> use pointer for merge tech) // unordered_set by value: __gnu_pbds::null_type // no erase(iterator) #include using __gnu_pbds::gp_hash_table; // https://codeforces.com/blog/entry/62393 #include struct Hash { static uint64_t splitmix64(uint64_t x) { // http://xorshift.di.unimi.it/splitmix64.c x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = std::chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); } size_t operator()(const pair &a) const { return operator()((uint64_t)a.first << 32 | a.second); } }; template using Set = gp_hash_table; template using Map = gp_hash_table; // iterator find_by_order(k): 0-indexed // size_type order_of_key(key): min id s.t. >= key #include #include template using rbtree = __gnu_pbds::tree< K, V, std::less, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update >; int N, Q; vector A; vector O, L, R, X, Y, K; vector brute() { vector ans(Q, 0); auto as = A; for (int q = 0; q < Q; ++q) { if (O[q] == 1) { for (int i = L[q]; i < R[q]; ++i) if (as[i] == X[q]) as[i] = Y[q]; } else { vector bs(as.begin() + L[q], as.begin() + R[q]); sort(bs.begin(), bs.end()); bs.erase(unique(bs.begin(), bs.end()), bs.end()); int lo = 0, hi = (int)bs.size() + K[q]; for (; lo + 1 < hi; ) { const int mid = lo + (hi - lo) / 2; // ex in [1, mid] int ex = mid; ex -= (upper_bound(bs.begin(), bs.end(), mid) - bs.begin()); ((ex >= K[q]) ? hi : lo) = mid; } ans[q] = hi; } } return ans; } namespace fast { constexpr int MAX_Y = 1010; int U, V; vector as; rbtree freq[MAX_Y]; vector> lz[MAX_Y]; void add(int u, int a, int f) { auto it = freq[u].find(a); if (it != freq[u].end()) { it->second += f; if (!it->second) freq[u].erase(it); } else { freq[u][a] = f; } } void push(int u) { Map ma; for (; lz[u].size(); ) { const int a = lz[u].back().first; const int b = lz[u].back().second; lz[u].pop_back(); int c = b; auto it = ma.find(b); if (it != ma.end()) { c = it->second; } ma[a] = c; } const int l = u * V; const int r = min((u + 1) * V, N); for (int i = l; i < r; ++i) { auto it = ma.find(as[i]); if (it != ma.end()) { as[i] = it->second; } } } vector run() { V = sqrt(N); U = (N + V - 1) / V; cerr<<"U = "<