[BZOJ2120]数颜色(莫队算法)

Description

墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问。墨墨会像你发布如下指令: 1、 Q L R代表询问你从第L支画笔到第R支画笔*有几种不同颜色的画笔。 2、 R P Col 把第P支画笔替换为颜色Col。为了满足墨墨的要求,你知道你需要干什么了吗?

带修改莫队,给每个询问加一个权值时间tim,询问的时候让时光回溯

Code

#include <cstdio>
#include <algorithm>
#include <cmath>
#define N 10010
using namespace std; int n,m,col[N],now[N],bl[N],Tim,cnt,Ans[N],sum,Scol[N*100],l,r;
struct change{
int p,v,pre;
change(){}
change(int a,int b,int c):p(a),v(b),pre(c){}
}c[N/10];
struct query{
int tim,l,r,id;
query(){}
query(int a,int b,int c,int d):l(a),r(b),tim(c),id(d){}
friend bool operator <(query a,query b){
return (bl[a.l]==bl[b.l])?(a.r==b.r?a.tim<b.tim:a.r<b.r):a.l<b.l;
}
}q[N]; inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
} void upd(int x,int d){
Scol[x]+=d;
if(d>0) sum+=(Scol[x]==1);
else sum-=(Scol[x]==0);
}
void go(int x,int d){
if(l<=x&&x<=r) upd(d,1),upd(col[x],-1);
col[x]=d;
} int main(){
n=read(),m=read();int blo=sqrt(n);
for(int i=1;i<=n;++i) col[i]=now[i]=read(),bl[i]=i/blo+1;
for(int i=1;i<=m;++i){
char ch;for(ch=getchar();ch!='Q'&&ch!='R';ch=getchar());
int x=read(),y=read();
if(ch=='Q') q[++cnt]=query(x,y,Tim,cnt);
else c[++Tim]=change(x,y,now[x]),now[x]=y;
}
sort(q+1,q+cnt+1);
for(int i=1,t=0;i<=cnt;++i){
for(;t<q[i].tim;t++) go(c[t+1].p,c[t+1].v);
for(;t>q[i].tim;t--) go(c[t].p,c[t].pre);
for(;l<q[i].l;l++) upd(col[l],-1);
for(;l>q[i].l;l--) upd(col[l-1],1);
for(;r<q[i].r;r++) upd(col[r+1],1);
for(;r>q[i].r;r--) upd(col[r],-1);
Ans[q[i].id]=sum;
}
for(int i=1;i<=cnt;printf("%d\n",Ans[i++]));
return 0;
}
上一篇:Cadence 操作技巧总结2:模块化布局


下一篇:Light OJ 1317 Throwing Balls into the Baskets 概率DP