BZOJ-2120 數顏色
阿新 • • 發佈:2022-05-24
數顏色
帶修莫隊 模板題
看到別人題解,發現有個小技巧,時間緯度在更改的時候直接 swap 當前值和要修改的值,下次回來的時候 swap 回去是一樣的,這樣就可以不用多記錄狀態了
https://fangkaipeng.com/?p=1504
我還發現非常 BZOJ 的資料和 AcWing 的資料相當奇怪,用分塊大小為 \(\sqrt{n}\) 作為分塊會更加快,而洛谷的資料用分塊大小為 \(n^{\frac{2}{3}}\) 會更快
我的猜測是資料範圍約束的問題,BZOJ 和 AcWing 的條件約束說修改的次數在於 1000 次以下,可能就導致了時間緯度修改的比較少,因此最優分塊趨近於 \(\sqrt{n}\)
https://www.acwing.com/problem/content/2523/
正常的複雜度分析來說,分塊大小應該為 \(n^{\frac{2}{3}}\),複雜度為 \(O(n^{\frac{5}{3}})\)
https://www.luogu.com.cn/problem/P1903
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <string> #include <queue> #include <functional> #include <map> #include <set> #include <cmath> #include <cstring> #include <deque> #include <stack> using namespace std; typedef long long ll; #define endl '\n' #define pii pair<int, int> const int maxn = 133333 + 10; const ll maxm = 1e6 + 10; const ll inf = 1e17 + 10; int num[maxn], pos[maxm], cnt[maxm]; int l = 1, r = 0, ans = 0, t = 0, nn = 0; int last[maxn]; struct node { int l, r, t, id; node(){} node(int _l, int _r, int _t, int _id){l = _l; r = _r; t = _t; id = _id;} }seg[maxn], change[maxn]; bool cmp(const node& a, const node& b) { return pos[a.l] ^ pos[b.l] ? pos[a.l] < pos[b.l] : (pos[a.r] ^ pos[b.r] ? pos[a.r] < pos[b.r] : a.t < b.t); } inline void add(int x) { ans += (++cnt[num[x]] == 1); } inline void del(int x) { ans -= (--cnt[num[x]] == 0); } inline void update(int x) { if(change[x].t >= l && change[x].t <= r) { del(change[x].t); swap(num[change[x].t], change[x].l); add(change[x].t); } else swap(num[change[x].t], change[x].l); } int main() { // ios::sync_with_stdio(false); // cin.tie(0); // cout.tie(0); // freopen("text.in", "rb", stdin); // freopen("text.out", "wb", stdout); int n, m; scanf("%d%d", &n, &m); int maxx = 0; for(int i=1; i<=n; i++) {cin >> num[i]; maxx = num[i] > maxx ? num[i] : maxx;} nn = pow(maxn, 2.0 / 3.0); for(int i=1; i<=maxx; i++) pos[i] = i / nn; int tq = 0, tr = 0; for(int i=0; i<m; i++) { char a; int x, y; scanf(" %c%d%d", &a, &x, &y); if(a == 'Q') { seg[tq] = node(x, y, tr, tq); tq++; } else { change[tr] = node(y, 0, x, 0); tr++; } } sort(seg, seg + tq, cmp); t = 0; for(int i=0; i<tq; i++) { while(t < seg[i].t) update(t++); while(t > seg[i].t) update(--t); while(r < seg[i].r) add(++r); while(l > seg[i].l) add(--l); while(r > seg[i].r) del(r--); while(l < seg[i].l) del(l++); last[seg[i].id] = ans; } for(int i=0; i<tq; i++) printf("%d\n", last[i]); return 0; }