2120: 数颜色
Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 2645 Solved: 1039
[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
Source
题解:
好像可以用bitset。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[10010]; 4 bitset<1000010> vis; 5 int main() 6 { 7 int n,m,i,l,r,sum,j; 8 char fh; 9 scanf("%d %d",&n,&m); 10 for(i=1;i<=n;i++)scanf("%d",&a[i]); 11 for(i=1;i<=m;i++) 12 { 13 scanf("\n%c %d %d",&fh,&l,&r); 14 if(fh=='Q') 15 { 16 vis.reset(); 17 sum=0; 18 for(j=l;j<=r;j++)if(vis[a[j]]==0){sum++;vis[a[j]]=1;} 19 printf("%d\n",sum); 20 } 21 else 22 { 23 a[l]=r; 24 } 25 } 26 return 0; 27 }
直接用莫队也可以。。。
好像重题了(见Bzoj2453)>_<
好像和 HH的项链 几乎一样。。。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 10010 4 #define MAXM 1000010 5 int n,a[MAXN],last[MAXN],pre[MAXM],block,pos[MAXN],h[MAXN]; 6 int read() 7 { 8 int s=0,fh=1;char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 10 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 11 return s*fh; 12 } 13 void cl(int k) 14 { 15 int l=(k-1)*block+1,r=min(n,k*block),i; 16 for(i=l;i<=r;i++)a[i]=last[i]; 17 sort(a+l,a+r+1); 18 } 19 void Change(int x,int c) 20 { 21 int i,t; 22 for(i=1;i<=n;i++)pre[h[i]]=0; 23 h[x]=c; 24 for(i=1;i<=n;i++) 25 { 26 t=last[i]; 27 last[i]=pre[h[i]]; 28 if(t!=last[i])cl(pos[i]); 29 pre[h[i]]=i; 30 } 31 } 32 int Find(int k,int ll) 33 { 34 int l=(k-1)*block+1,r=min(k*block,n),mid,t=0; 35 while(l<=r) 36 { 37 mid=(l+r)/2; 38 if(a[mid]>=ll)r=mid-1; 39 else if(a[mid]<ll)t=mid,l=mid+1; 40 } 41 if(t==0)return 0; 42 else return t-((k-1)*block+1)+1; 43 } 44 int Query(int l,int r) 45 { 46 int ans=0,i; 47 if(pos[l]==pos[r]) 48 { 49 for(i=l;i<=r;i++)if(last[i]<l)ans++; 50 } 51 else 52 { 53 for(i=l;i<=pos[l]*block;i++)if(last[i]<l)ans++; 54 for(i=(pos[r]-1)*block+1;i<=r;i++)if(last[i]<l)ans++; 55 for(i=pos[l]+1;i<=pos[r]-1;i++)ans+=Find(i,l); 56 } 57 return ans; 58 } 59 int main() 60 { 61 int M,i,m,s1,s2; 62 char fh[2]; 63 n=read();M=read(); 64 block=(int)sqrt(n); 65 memset(last,0,sizeof(last)); 66 memset(pre,0,sizeof(pre)); 67 for(i=1;i<=n;i++) 68 { 69 h[i]=read(); 70 last[i]=pre[h[i]]; 71 pre[h[i]]=i; 72 pos[i]=(i-1)/block+1; 73 } 74 if(block*block==n)m=n/block; 75 else m=n/block+1; 76 for(i=1;i<=m;i++)cl(i); 77 for(i=1;i<=M;i++) 78 { 79 scanf("\n%s",fh);s1=read();s2=read(); 80 if(fh[0]=='Q') 81 { 82 printf("%d\n",Query(s1,s2)); 83 } 84 else Change(s1,s2); 85 } 86 return 0; 87 }