BZOJ 2120 数颜色
2120: 数颜色
Time Limit: 6 Sec Memory Limit: 259 MBSubmit: 8311 Solved: 3419
[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
用pre[i]记录前一个和i相同颜色的球的所在位置
询问l到r时,如果pre[i]<l说明在l到i这一段没用和i颜色相同的球,则ans++
利用这种思路我们可以。。。分块
每一块内按pre[i]排序
BZOJ 2453 维护队列同理
#include <bits/stdc++.h> #define ll long long #define inf 1e9+10 using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=1e6+10; int n,m,block,pre[MAXN],last[MAXN],num,pos[MAXN],a[MAXN],b[MAXN]; inline void sor(int x){ int l=(x-1)*block+1;int r=min(x*block,n); for(int i=l;i<=r;i++) pre[i]=b[i]; sort(pre+l,pre+r+1); } inline int query(int x,int L){ int l=(x-1)*block+1;int r=min(x*block,n); int t=l; while(l<=r){ int mid=(l+r)>>1; if(pre[mid]<L) l=mid+1; else r=mid-1; } return l-t; } inline void rebuild(int t,int v){ for(int i=1;i<=n;i++){ last[a[i]]=0; } a[t]=v; for(int i=1;i<=n;i++){ int t=b[i]; b[i]=last[a[i]]; last[a[i]]=i; if(b[i]!=t) sor(pos[i]); } } inline void build(){ for(int i=1;i<=n;i++){ b[i]=last[a[i]]; last[a[i]]=i; pos[i]=(i-1)/block+1; } for(int i=1;i<=num;i++) sor(i); } inline int ask(int L,int R){ int ans=0; for(int i=pos[L]+1;i<pos[R];i++){ ans+=query(i,L); } if(pos[L]==pos[R]){ for(int i=L;i<=R;i++) if(b[i]<L) ans++; } else{ for(int i=L;i<=pos[L]*block;i++) if(b[i]<L) ans++; for(int i=(pos[R]-1)*block+1;i<=R;i++) if(b[i]<L) ans++; } return ans; } int main(){ //freopen("All.in","r",stdin); //freopen("zem.out","w",stdout); n=read();m=read(); block=(int)sqrt(1.0*n+log(n*2)/log(2)); if(n%block) num=n/block+1; else num=n/block; for(int i=1;i<=n;i++){ a[i]=read(); } build(); while(m--){ char op[5]; scanf("%s",op); if(op[0]=='Q'){ int L=read();int R=read(); printf("%d\n",ask(L,R)); } else{ int t=read();int v=read(); rebuild(t,v); } } return 0; }