[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;
}

猜你喜欢

转载自www.cnblogs.com/void-f/p/9090490.html
今日推荐