[Bzoj2120]数颜色

题目链接

如果没有这个修改操作,那么就可以主席树/树状数组乱搞,可以没有如果QAQ。

所以选择莫队来乱搞这个修改操作。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxm = 1e6 + 10;
 4 const int maxn = 133334;
 5 typedef long long ll;
 6 int a[maxm], p[maxm], now[maxm], color[maxm];
 7 struct Q {
 8     int l, r, tim, id;
 9 }q[maxm];
10 struct C {
11     int pos, now, old;
12 }c[maxm];
13 bool cmp(Q a, Q b) {
14     return p[a.l] == p[b.l] ? (p[a.r] == p[b.r] ? a.tim < b.tim : a.r < b.r) : a.l < b.l;
15 }
16 int Ans, ans[maxm], l, r, t;
17 void revise(int x, int val) {
18     color[x] += val;
19     if (val > 0)
20         Ans += color[x] == 1;
21     if (val < 0)
22         Ans -= color[x] == 0;
23 }
24 void go(int x, int d) {
25     if (l <= x && x <= r)
26         revise(d, 1), revise(a[x], -1);
27     a[x] = d;
28 }
29 int main() {
30     int n, m;
31     scanf("%d%d", &n, &m);
32     Ans = r = t = 0, l = 1;
33     int len = pow(n, 0.666666), lenq = 0, lenc = 0;
34     for (int i = 1; i <= n; i++)
35         scanf("%d", &a[i]), now[i] = a[i], p[i] = i / len + 1;
36     char s[3];
37     int x, y;
38     for (int i = 1; i <= m; i++) {
39         scanf("%s%d%d", s, &x, &y);
40         if (s[0] == 'Q') ++lenq, q[lenq] = { x, y, lenc, lenq };
41         if (s[0] == 'R') ++lenc, c[lenc] = { x, y, now[x] }, now[x] = y;
42     }
43     sort(q + 1, q + 1 + lenq, cmp);
44     for (int i = 1; i <= lenq; i++) {
45         while (t < q[i].tim)go(c[t + 1].pos, c[t + 1].now), t++;
46         while (t > q[i].tim)go(c[t].pos, c[t].old), t--;
47         while (l < q[i].l)revise(a[l], -1), l++;
48         while (l > q[i].l)revise(a[l - 1], 1), l--;
49         while (r < q[i].r)revise(a[r + 1], 1), r++;
50         while (r > q[i].r)revise(a[r], -1), r--;
51         ans[q[i].id] = Ans;
52     }
53     for (int i = 1; i <= lenq; i++)
54         printf("%d
", ans[i]);
55 }
原文地址:https://www.cnblogs.com/sainsist/p/11551539.html