BZOJ 2120 数颜色

题解:带修改莫队

左右端点相同按?排序

问题:不会证时间复杂度

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=10009;
const int maxc=1000009;
const int SIZ=200;

int n,m,TT;
int a[maxn];

int cntupd;
int upp[maxn],upc[maxn];

int c[maxc];

int qx[maxn],qy[maxn],last[maxn],ans[maxn];
int p[maxn];
bool cmp(const int &rhs1,const int &rhs2){
	if((qx[rhs1]-1)/SIZ==(qx[rhs2]-1)/SIZ){
		return qy[rhs1]<qy[rhs2];
	}else{
		return qx[rhs1]<qx[rhs2];
	}
}

int main(){
	scanf("%d%d",&n,&TT);
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	int lastupd=0;
	while(TT--){
		char opty=getchar();
		int x,y;
		while(opty!='Q'&&opty!='R')opty=getchar();
		scanf("%d%d",&x,&y);
		if(opty=='Q'){
			++m;
			qx[m]=x;
			qy[m]=y;
			last[m]=lastupd;
		}else{
			++cntupd;
			upp[cntupd]=x;
			upc[cntupd]=y;
			lastupd=cntupd;
		}
	}
	
	for(int i=1;i<=m;++i)p[i]=i;
	sort(p+1,p+1+m,cmp);

	int l=1,r=0,nowupd=0,nowans=0;
	for(int i=1;i<=m;++i){
		int t=p[i];
		int x=qx[t];
		int y=qy[t];
		while(nowupd<last[t]){
			++nowupd;
			swap(a[upp[nowupd]],upc[nowupd]);
			if(upp[nowupd]>=l&&upp[nowupd]<=r){
				if(++c[a[upp[nowupd]]]==1)++nowans;
				if(--c[upc[nowupd]]==0)--nowans;
			}
		}
		while(nowupd>last[t]){
			swap(a[upp[nowupd]],upc[nowupd]);
			if(upp[nowupd]>=l&&upp[nowupd]<=r){
				if(++c[a[upp[nowupd]]]==1)++nowans;
				if(--c[upc[nowupd]]==0)--nowans;
			}
			--nowupd;
		}
		
		while(l<x){
			if(--c[a[l]]==0)--nowans;
			++l;
		}
		while(l>x){
			--l;
			if(++c[a[l]]==1)++nowans;
		}
		
		while(r<y){
			++r;
			if(++c[a[r]]==1)++nowans;
		}
		while(r>y){
			if(--c[a[r]]==0)--nowans;
			--r;
		}
		ans[t]=nowans;
	}
	for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
	return 0;
}

  

posted @ 2018-02-23 19:30  ws_zzy  阅读(118)  评论(0编辑  收藏  举报