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

2120: 数颜色

Time Limit: 6 Sec  Memory Limit: 259 MB
Submit: 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

Sample Output

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 }

 

posted @ 2018-03-17 16:06  MJT12044  阅读(243)  评论(0编辑  收藏  举报