[國家集訓隊]數顏色 / 維護佇列 (帶修改莫隊
阿新 • • 發佈:2018-12-18
題目連結
題解
樹套樹做法暫時不會,先坑著
帶修改的莫隊
在普通莫隊基礎上加一個時間量
修改時調整區間,同時調整時間
具體看程式碼
Code
#include<bits/stdc++.h> #define LL long long #define RG register using namespace std; const int N = 2000010, M = 50010; int n, m, C[N], belong[N]; struct qus { int l, r, id, tim;//tim記錄在這次詢問之前最近它的修改 bool operator <(qus z) const { if (belong[l] == belong[z.l]) { if (belong[r] == belong[z.r]) return tim < z.tim; return r < z.r; } return l < z.l; } }q[M]; struct node { int pos, v; }o[M]; //o記錄修改操作,q記錄詢問 int cnt1, cnt2; int tot[N], ans, a[M]; inline void del(int c) {if(!(--tot[c])) ans--;}//刪掉 inline void add(int c) {if(++tot[c] == 1) ans++;}//新增 inline void change(int now, int k) { if (q[k].l <= o[now].pos && o[now].pos <= q[k].r) del(C[o[now].pos]), add(o[now].v); swap(C[o[now].pos], o[now].v);//這裡是交換,因為後面撤銷操作需要掉換回來 return ; } inline int gi() { RG int x = 0; RG char c = getchar(); bool f = 0; while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1; while (c >= '0' && c <= '9') x = x*10+c-'0', c = getchar(); return f ? -x : x; } int main() { int n = gi(), m = gi(), siz = pow(n, 0.666666666666);//siz為塊的大小 for (RG int i = 1; i <= n; i++) C[i] = gi(), belong[i] = (i-1)/siz+1; char type; while (m--) { scanf("\n%c", &type); if (type == 'Q') { q[++cnt1].l = gi(); q[cnt1].r = gi(); q[cnt1].id = cnt1; q[cnt1].tim = cnt2; } else o[++cnt2].pos = gi(), o[cnt2].v = gi(); } sort(q+1, q+1+cnt1); int l = 1, r = 0, now = 0; for (int i = 1; i <= cnt1; i++) { while (l > q[i].l) add(C[--l]); while (l < q[i].l) del(C[l++]); while (r < q[i].r) add(C[++r]); while (r > q[i].r) del(C[r--]); while (now < q[i].tim) change(++now, i); while (now > q[i].tim) change(now--, i); a[q[i].id] = ans; } for (int i = 1; i <= cnt1; i++) printf("%d\n", a[i]); return 0; }