【luogu P1903 [国家集训队]数颜色】 题解

题目链接:https://www.luogu.org/problemnew/show/P1903

裸的。。。带修莫队。。。

比较麻烦吧(对我来说是的)

两个变量分开记录查询和修改操作。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define ri register
 6 using namespace std;
 7 const int maxn = 1000003;
 8 int n, m, bl, answer = 0, qnum = 0, unum = 0, curR, curL, now;
 9 int ans[maxn],a[maxn],cnt[maxn];
10 struct query{
11     int l, r, p, t;
12     bool operator < (const query &x) const {
13     if(l / bl != x.l / bl) return l / bl < x.l / bl;
14     if(r / bl != x.r / bl) return r / bl < x.r / bl;
15     return t < x.t;
16   }
17 }q[maxn];
18 struct update{
19     int pos, val;
20 }u[maxn];
21 inline void add(int pos) {
22   if(++ cnt[pos] == 1) answer ++;
23 }
24 inline void remove(int pos) {
25   if(-- cnt[pos] == 0) answer --;
26 }
27 inline void change(int now, int i) {
28   if(q[i].l <= u[now].pos && u[now].pos <= q[i].r) {
29     if( --cnt[a[u[now].pos]] == 0 ) answer--;
30     if( ++cnt[u[now].val] == 1)      answer++; 
31   }
32   swap(a[u[now].pos], u[now].val);
33 }
34 int main()
35 {
36     scanf("%d%d",&n,&m);
37     bl = pow(n,1.0/3);
38     for(ri int i = 1; i <= n; i++)
39     scanf("%d",&a[i]);
40     for(ri int i = 1; i <= m; i++)
41     {
42     int ch, x, y;
43     while((ch = getchar()) != 'Q' && ch != 'R');
44     scanf("%d%d", &x, &y);
45     if(ch == 'Q') {
46       q[++ qnum].l = x;
47       q[qnum].r = y;
48       q[qnum].t = unum;
49       q[qnum].p = qnum;
50     } else {
51       u[++unum].pos = x;
52       u[unum].val = y;
53     }
54   }
55     sort(q+1,q+qnum+1);
56     curL = q[1].l, curR = curL - 1, now = 0;
57   for(ri int i = 1; i <= qnum; i ++) {
58     while(curL < q[i].l) remove(a[curL ++]);
59     while(curL > q[i].l) add(a[-- curL]);
60     while(curR < q[i].r) add(a[++ curR]);
61     while(curR > q[i].r) remove(a[curR --]);
62     while(now < q[i].t) change(++ now, i);
63     while(now > q[i].t) change(now --, i);
64     ans[q[i].p] = answer;
65   }
66     for(ri int i = 1; i <= qnum; i++)
67         printf("%d\n",ans[i]);
68     return 0;
69 }

 

posted @ 2018-04-01 15:41  Misaka_Azusa  阅读(216)  评论(0编辑  收藏  举报
Live2D