Luogu传送门
带修莫队板子题。
就是再多开一维时间轴,把每次修改修改前的颜色和修改后的颜色都记录下来。
离线处理。
枚举操作时,类似于普通的莫队,while(操作时间)
看看是该插入还是删除,然后直接修改就完了。
贴下代码吧,直接看代码比较好理解。
#include <bits/stdc++.h> #define get_B(x) x / B using namespace std; namespace IO{ inline int read(){ int x = 0; char ch = getchar(); while(!isdigit(ch)) ch = getchar(); while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); return x; } template <typename T> inline void write(T x){ if(x > 9) write(x / 10); putchar(x % 10 + '0'); } } using namespace IO; const int N = 2e5 + 10; const int M = 1e6 + 10; int n, m, B, res; int c[N], col[N]; char op[3]; struct Upd{ int pos, col, pre; }p[N]; struct Qry{ int l, r, t, pos; friend bool operator < (Qry a, Qry b){ if(get_B(a.l) != get_B(b.l)) return get_B(a.l) < get_B(b.l); return get_B(a.r) != get_B(b.r) ? get_B(a.r) < get_B(b.r) : a.t < b.t; } }q[N]; int tp, tq; int vis[M], ans[N]; int main(){ n = read(), m = read(); for(int i = 1; i <= n; ++i) col[i] = c[i] = read(); for(int i = 1; i <= m; ++i){ scanf("%s", op); int x = read(), y = read(); if(op[0] == 'R') p[++tp] = (Upd){x, y, c[x]}, c[x] = y; else q[++tq] = (Qry){x, y, tp, tq}; } if(!tq) return 0; B = pow(n, 0.7); sort(q + 1, q + 1 + tq); int l = 1, r = 0, t = 0; for(int i = 1; i <= tq; ++i){ while(l > q[i].l) res += !vis[col[--l]]++; while(l < q[i].l) res -= !--vis[col[l++]]; while(r < q[i].r) res += !vis[col[++r]]++; while(r > q[i].r) res -= !--vis[col[r--]]; while(t > q[i].t){ int x = p[t].pos; if(l <= x && x <= r) res -= !--vis[col[x]]; col[x] = p[t--].pre; if(l <= x && x <= r) res += !vis[col[x]]++; } while(t < q[i].t){ int x = p[++t].pos; if(l <= x && x <= r) res -= !--vis[col[x]]; col[x] = p[t].col; if(l <= x && x <= r) res += !vis[col[x]]++; } ans[q[i].pos] = res; } for(int i = 1; i <= tq; ++i) write(ans[i]), puts(""); return 0; }\[\_EOF\_ \]