bzoj2453/2120 数颜色
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2120
http://www.lydsy.com/JudgeOnline/problem.php?id=2453
【题解】
带修改莫队,分块大小n^(2/3),总复杂度O(n^(5/3))
简单说下,就是按照开始block,结束block,时间顺序分别排序后,不仅按照两个端点像莫队那样做,还把时间也按莫队那样做,就是维护恰好到询问时间的所有修改。
# include <math.h> # include <stdio.h> # include <string.h> # include <iostream> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 2e5 + 10, N = 2e6 + 10; const int mod = 1e9+7; # define RG register # define ST static int n, m, a[M], t[M]; int BLOCK, bl[M]; struct pa { int x, y, t; pa() {} pa(int x, int y, int t) : x(x), y(y), t(t) {} friend bool operator < (pa a, pa b) { return bl[a.x] < bl[b.x] || (bl[a.x] == bl[b.x] && bl[a.y] < bl[b.y]) || (bl[a.x] == bl[b.x] && bl[a.y] == bl[b.y] && a.t < b.t); } }q[M]; struct paa { int x, oc, nc, t; paa() {} paa(int x, int oc, int nc, int t) : x(x), oc(oc), nc(nc), t(t) {} }p[M]; int pn, qn, ans[M]; int c[N], cnt, L, R; inline void add(int x) { ++ c[a[x]]; if(c[a[x]] == 1) ++cnt; } inline void del(int x) { -- c[a[x]]; if(c[a[x]] == 0) --cnt; } inline void DEL(int x) { --c[x]; if(c[x] == 0) --cnt; } inline void ADD(int x) { ++c[x]; if(c[x] == 1) ++cnt; } int main() { cin >> n >> m; BLOCK = pow(n, 2.0/3.0); for (int i=1; i<=n; ++i) { scanf("%d", a+i); t[i] = a[i]; bl[i] = (i-1)/BLOCK + 1; } char opt[23]; for (int i=1, x, y; i<=m; ++i) { scanf("%s%d%d", opt, &x, &y); if(opt[0] == 'R') { p[++pn] = paa(x, t[x], y, i); t[x] = y; } else q[++qn] = pa(x, y, i); ans[i] = 0; } sort(q+1, q+qn+1); L = 1, R = 0; for (int i=1, j=1; i<=qn; ++i) { while(j <= pn && q[i].t > p[j].t) { if(L <= p[j].x && p[j].x <= R) DEL(p[j].oc), ADD(p[j].nc); a[p[j].x] = p[j].nc; ++j; } while(j-1 >= 1 && q[i].t < p[j-1].t) { --j; if(L <= p[j].x && p[j].x <= R) DEL(p[j].nc), ADD(p[j].oc); a[p[j].x] = p[j].oc; } while(R < q[i].y) ++R, add(R); while(R > q[i].y) del(R), --R; while(L > q[i].x) --L, add(L); while(L < q[i].x) del(L), ++L; ans[q[i].t] = cnt; } for (int i=1; i<=m; ++i) if(ans[i]) printf("%d\n", ans[i]); return 0; }