P1903 [國家集訓隊]數顏色 / 維護隊列
阿新 • • 發佈:2018-10-16
read 程序 wap tdi 但是 main add 時間排序 sort
毒瘤數據卡普通莫隊!!
這道題跟普通的莫隊題目差不多,但是多了一個修改操作。
所以帶修莫隊就橫空出世了。
普通莫隊記錄左端點和右端點,那麽這裏就再記錄一個時間軸,表示當時已經執行過幾次修改。
之後莫隊模板就有六個while,前四個是一樣的。
最後兩個判斷當前修改次數和目標修改次數的關系。這個就是靈魂了。
重點看這個時間軸上的修改吧。
void change(int idx, int i) { if(q[i].l <= c[idx].p && c[idx].p <= q[i].r)// 當修改點在詢問區間內才需要維護答案 { del(a[c[idx].p]); add(c[idx].col); } std::swap(a[c[idx].p], c[idx].col);// 很巧妙的一個操作,這樣操作答案不變,程序更簡潔 }
完整代碼:
#include<cstdio> #include<cmath> #include<algorithm> const int maxn = 50005; struct Query { int l, r, id, pre; } q[maxn]; int q_tot; struct Change { int p, col; } c[maxn]; int c_tot; int belong[maxn], block; int a[maxn]; int out[maxn]; int n, m; int l, r, res, changed; int cnt[1000005]; bool cmp(Query x, Query y)// 按照左右端點所在塊排序,再按時間排序 { if(belong[x.l] != belong[y.l]) return belong[x.l] < belong[y.l]; if(belong[x.r] != belong[y.r]) return belong[x.r] < belong[y.r]; return x.pre < y.pre; } int read() { int ans = 0, s = 1; char ch = getchar(); while(ch > ‘9‘ || ch < ‘0‘){ if(ch == ‘-‘) s = -1; ch = getchar(); } while(ch >= ‘0‘ && ch <= ‘9‘) ans = (ans << 3) + (ans << 1) + ch - ‘0‘, ch = getchar(); return s * ans; } void add(int x) { if(++cnt[x] == 1) res++; } void del(int x) { if(--cnt[x] == 0) res--; } void change(int idx, int i) { if(q[i].l <= c[idx].p && c[idx].p <= q[i].r) { del(a[c[idx].p]); add(c[idx].col); } std::swap(a[c[idx].p], c[idx].col); } void moqueue() { block = pow(n, 0.6666667);// 塊大小要換成這樣 for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1; std::sort(q + 1, q + q_tot + 1, cmp); l = 1, r = 0, res = 0, changed = 0; for(int i = 1; i <= q_tot; i++) { while(r < q[i].r) add(a[++r]); while(r > q[i].r) del(a[r--]); while(l > q[i].l) add(a[--l]); while(l < q[i].l) del(a[l++]); while(changed < q[i].pre) change(++changed, i);// 改少了 while(changed > q[i].pre) change(changed--, i);// 改多了 out[q[i].id] = res; } } int main() { n = read(), m = read(); for(int i = 1; i <= n; i++) a[i] = read(); for(int i = 1; i <= m; i++) { char opt[3]; scanf("%s", opt); if(opt[0] == ‘Q‘) { int x = read(), y = read(); q[++q_tot] = (Query){x, y, q_tot, c_tot}; } else if(opt[0] == ‘R‘) { int p = read(), col = read(); c[++c_tot] = (Change){p, col}; } } moqueue(); for(int i = 1; i <= q_tot; i++) printf("%d\n", out[i]); return 0; }
P1903 [國家集訓隊]數顏色 / 維護隊列