BZOJ2120 数颜色 —— 待修改莫队
题目链接:https://vjudge.net/problem/HYSBZ-2120
2120: 数颜色
Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 6898 Solved: 2781
[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
题意:
查询区间颜色种数,且带修改。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 1e6+10; 18 19 int val[MAXN], tmp[MAXN]; 20 int block, sum[MAXN], Ans[MAXN]; 21 int num1, num2; 22 23 struct Node 24 { 25 //index记录查询的编号, t记录查询时执行了多少步修改 26 int l, r, index, t; 27 bool operator<(const Node&x) const{ 28 if(l/block!=x.l/block) return l/block<x.l/block; 29 else if(r!=x.r) return r<x.r; 30 else return t<x.t; 31 } 32 }q[MAXN]; 33 34 struct 35 { 36 //preCol记录修改前pos位的颜色, nowCol记录修改后pos位的颜色 37 int pos, nowCol, preCol; 38 }op[MAXN]; 39 40 int L, R, T, ans; 41 void modifyTime(int pos, int col) 42 { 43 if(L<=pos && pos<=R) 44 { 45 sum[val[pos]]--; 46 if(sum[val[pos]]==0) ans--; 47 val[pos] = col; 48 sum[val[pos]]++; 49 if(sum[val[pos]]==1) ans++; 50 } 51 else val[pos] = col; 52 } 53 54 void add(int pos) 55 { 56 sum[val[pos]]++; 57 if(sum[val[pos]]==1) ans++; 58 } 59 60 void del(int pos) 61 { 62 sum[val[pos]]--; 63 if(sum[val[pos]]==0) ans--; 64 } 65 66 void work() 67 { 68 L = 1, R = 0, T = 0, ans = 0; 69 memset(sum, 0, sizeof(sum)); 70 for(int i = 1; i<=num1; i++) 71 { 72 while(T<q[i].t) T++, modifyTime(op[T].pos, op[T].nowCol); 73 while(T>q[i].t) modifyTime(op[T].pos, op[T].preCol), T--; 74 while(L<q[i].l) del(L), L++; 75 while(L>q[i].l) L--, add(L); 76 while(R<q[i].r) R++, add(R); 77 while(R>q[i].r) del(R), R--; 78 Ans[q[i].index] = ans; 79 } 80 } 81 82 int main() 83 { 84 int n, m; 85 while(scanf("%d%d", &n,&m)!=EOF) 86 { 87 block = sqrt(n); 88 for(int i = 1; i<=n; i++) 89 { 90 scanf("%d", &val[i]); 91 tmp[i] = val[i]; 92 } 93 94 num1 = num2 = 0; 95 for(int i = 1; i<=m; i++) 96 { 97 char s[2]; int x, y; 98 scanf("%s%d%d", s, &x, &y); 99 if(s[0]=='Q') 100 { 101 q[++num1].index = num1; 102 q[num1].t = num2; 103 q[num1].l = x; 104 q[num1].r = y; 105 } 106 else //tmp用于记录动态修改时每个位置上的颜色 107 { 108 op[++num2].pos = x; 109 op[num2].nowCol = y; 110 op[num2].preCol = tmp[x]; 111 tmp[x] = y; 112 } 113 } 114 115 sort(q+1, q+1+num1); 116 work(); 117 for(int i = 1; i<=num1; i++) 118 printf("%d\n", Ans[i]); 119 } 120 }
直接暴力也行:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 1e6+10; 18 19 int val[MAXN], tmp[MAXN]; 20 int block, sum[MAXN], Ans[MAXN]; 21 int num1, num2; 22 23 struct Node 24 { 25 //index记录查询的编号, t记录查询时执行了多少步修改 26 int l, r, index, t; 27 }q[MAXN]; 28 29 struct 30 { 31 //preCol记录修改前pos位的颜色, nowCol记录修改后pos位的颜色 32 int pos, nowCol, preCol; 33 }op[MAXN]; 34 35 int L, R, T, ans; 36 void modifyTime(int pos, int col) 37 { 38 if(L<=pos && pos<=R) 39 { 40 sum[val[pos]]--; 41 if(sum[val[pos]]==0) ans--; 42 val[pos] = col; 43 sum[val[pos]]++; 44 if(sum[val[pos]]==1) ans++; 45 } 46 else val[pos] = col; 47 } 48 49 void add(int pos) 50 { 51 sum[val[pos]]++; 52 if(sum[val[pos]]==1) ans++; 53 } 54 55 void del(int pos) 56 { 57 sum[val[pos]]--; 58 if(sum[val[pos]]==0) ans--; 59 } 60 61 void work() 62 { 63 L = 1, R = 0, T = 0, ans = 0; 64 memset(sum, 0, sizeof(sum)); 65 for(int i = 1; i<=num1; i++) 66 { 67 while(T<q[i].t) T++, modifyTime(op[T].pos, op[T].nowCol); 68 while(T>q[i].t) modifyTime(op[T].pos, op[T].preCol), T--; 69 while(L<q[i].l) del(L), L++; 70 while(L>q[i].l) L--, add(L); 71 while(R<q[i].r) R++, add(R); 72 while(R>q[i].r) del(R), R--; 73 Ans[q[i].index] = ans; 74 } 75 } 76 77 int main() 78 { 79 int n, m; 80 while(scanf("%d%d", &n,&m)!=EOF) 81 { 82 for(int i = 1; i<=n; i++) 83 { 84 scanf("%d", &val[i]); 85 tmp[i] = val[i]; 86 } 87 88 num1 = num2 = 0; 89 for(int i = 1; i<=m; i++) 90 { 91 char s[2]; int x, y; 92 scanf("%s%d%d", s, &x, &y); 93 if(s[0]=='Q') 94 { 95 q[++num1].index = num1; 96 q[num1].t = num2; 97 q[num1].l = x; 98 q[num1].r = y; 99 } 100 else //tmp用于记录动态修改时每个位置上的颜色 101 { 102 op[++num2].pos = x; 103 op[num2].nowCol = y; 104 op[num2].preCol = tmp[x]; 105 tmp[x] = y; 106 } 107 } 108 109 work(); 110 for(int i = 1; i<=num1; i++) 111 printf("%d\n", Ans[i]); 112 } 113 }