2120: 数颜色(带修改莫队)
2120: 数颜色
Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 7599 Solved: 3087
[Submit][Status][Discuss]
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
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
4
3
4
HINT
对于100%的数据,N≤10000,M≤10000,修改操作不多于1000次,所有的输入数据中出现的所有整数均大于等于1且不超过10^6。
2016.3.2新加数据两组by Nano_Ape
分析
待修改莫队。
与普通莫队相比较,多了修改操作,那么对于每一个查询[l,r],再记录一个t值,表示当前询问最近的一次修改的编号,即询问前,要操作t次。
排序时t为第三关键字。
然后维护三个指针L,R,T。与普通莫队不同的是:对于当前询问,t>T,那么依次更新t+1,t+2...T次操作;对于t<T,那么减去T,T-1...t。
code
1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 5 using namespace std; 6 7 const int N = 100100; 8 9 struct Query{ 10 int l,r,id,t,k; 11 //依次表示 查询的左端点,右端点,查询序号,查询前的最近一次修改,左端点属于的块 12 }q[N]; 13 struct Change{ 14 int p,x,y; 15 //依次表示 修改的位置,修改后的值,修改前的值(原值) 16 }c[N]; 17 int last[N],ans[N],cnt[1000100],v[N]; 18 int C,D,Ans,L,R,T,n,m; 19 char s[10]; 20 21 bool cmp(Query a,Query b) { 22 if (a.k != b.k) return a.k < b.k; 23 if (a.r != b.r) return a.r < b.r; 24 return a.t < b.t; 25 } 26 void add(int x) { 27 cnt[x] ++; 28 if (cnt[x] == 1) Ans ++; 29 } 30 void del(int x) { 31 cnt[x] --; 32 if (cnt[x] == 0) Ans --; 33 } 34 void update(int p,int x) { // 将p位置修改为x 35 if (L <= p && p <= R) del(v[p]),add(x); 36 v[p] = x; 37 } 38 void work() { 39 L = 1,R = 0,T = 0; 40 for (int i=1; i<=C; ++i) { 41 while (T < q[i].t) update(c[T+1].p,c[T+1].x),T++; 42 while (T > q[i].t) update(c[T].p,c[T].y),T--; 43 44 while (L < q[i].l) del(v[L]),L++; 45 while (L > q[i].l) L--,add(v[L]); 46 while (R < q[i].r) R++,add(v[R]); 47 while (R > q[i].r) del(v[R]),R--; 48 49 ans[q[i].id] = Ans; 50 } 51 } 52 int main() { 53 scanf("%d%d",&n,&m); 54 int B = pow(double(n),2.0/3.0); 55 for (int i=1; i<=n; ++i) 56 scanf("%d",&v[i]),last[i] = v[i]; 57 for (int a,b,i=1; i<=m; ++i) { 58 scanf("%s%d%d",s,&a,&b); 59 if (s[0]=='Q') { 60 q[++C].l = a;q[C].r = b;q[C].t = D;q[C].k = (n-1)/B+1;q[C].id = C; 61 } 62 else { 63 c[++D].p = a;c[D].x = b;c[D].y = last[a];last[a] = b; 64 } 65 } 66 sort(q+1,q+C+1,cmp); 67 work(); 68 for (int i=1; i<=C; ++i) 69 printf("%d\n",ans[i]); 70 return 0; 71 }