BZOJ 2120: 数颜色(带修改莫队)

题目传送门:数颜色

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

Input

第1行两个整数N,M,分别代表初始画笔的数量以及墨墨会做的事情的个数。第2行N个整数,分别代表初始画笔排中第i支画笔的颜色。第3行到第2+M行,每行分别代表墨墨会做的一件事情,格式见题干部分。

Output

对于每一个Query的询问,你需要在对应的行中给出一个数字,代表第L支画笔到第R支画笔中共有几种不同颜色的画笔。

Sample Input

6 5
1 2 3 4 5 5
Q 1 4
Q 2 6
R 1 2
Q 1 4
Q 2 6

Sample Output

4
4
3
4

HINT

对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。

解题思路:

  这题可以用带修改的莫队来写。加一个结构体来存要修改的信息。在用来查询的结构体中加一个变量来记录在查询这个区间之前有几次修改操作。然后对每个区间进行查询时先进行修改。

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N = 10000+100;
 7 const int M = 1e6+100;
 8 int a[N],num[M],pre[N],last[N];
 9 struct node
10 {
11     int l,r,t,id;
12 } q[N];
13 struct ccc
14 {
15     int x,y,last;
16 } c[N];
17 bool cmp(node x,node y)
18 {
19     if (pre[x.l]==pre[y.l])
20     {
21         if (x.r==y.r) return x.t<y.t;
22         return pre[x.r]<pre[y.r];
23     }
24     return x.l<y.l;
25 }
26 int n,m,cnt,ans[N];
27 void add(int x)
28 {
29     if (!num[a[x]]) cnt++;
30     num[a[x]]++;
31 }
32 void del(int x)
33 {
34     num[a[x]]--;
35     if (!num[a[x]]) cnt--;
36 }
37 void change(int x,int c,int L,int R)
38 {
39     if (x>=L&&x<=R)
40     {
41         del(x);
42         a[x]=c;
43         add(x);
44     }
45     else a[x]=c;
46 }
47 int main()
48 {
49     char s[5];
50     int m1=0,m2=0,x,y,sz;
51     scanf("%d%d",&n,&m);
52     sz=sqrt(n);
53     for (int i=1; i<=n; i++)
54     {
55         scanf("%d",&a[i]);
56         last[i]=a[i];
57         pre[i]=i/sz;
58     }
59     for (int i=1; i<=m; i++)
60     {
61         scanf("%s%d%d",s,&x,&y);
62         if (s[0]=='Q')
63         {
64             q[++m1].l=x,q[m1].r=y;
65             q[m1].id=m1,q[m1].t=m2;
66         }
67         else if (s[0]=='R')
68         {
69             c[++m2].x=x,c[m2].y=y;
70             c[m2].last=last[x],last[x]=y;
71         }
72     }
73     sort(q,q+m1,cmp);
74     int L=1,R=0,t=0;
75     for (int i=1; i<=m1; i++)
76     {
77         while(t<q[i].t) t++,change(c[t].x,c[t].y,L,R);
78         while(t>q[i].t) change(c[t].x,c[t].last,L,R),t--;
79         while(L<q[i].l) del(L++);
80         while(L>q[i].l) add(--L);
81         while(R<q[i].r) add(++R);
82         while(R>q[i].r) del(R--);
83         ans[q[i].id]=cnt;
84     }
85     for (int i=1; i<=m1; i++) printf("%d
",ans[i]);
86     return 0;
87 }
带修改莫队
原文地址:https://www.cnblogs.com/l999q/p/9517994.html