luogu1903

(带修莫队题....有点卡常需要调整块的大小....最合适的位置为sz=(n^(2/3)),可通过基本不等式证明,(明天补树套树做法

题解:权值很小,数组可解决(权值过大应该考虑离散化),然后就是基本带修操作

#include <bits/stdc++.h>
#define ll long long
#define s second
#define f first
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=5e4+10;
const int NM=1e6+100;
using namespace std;
ll read(){  
    ll x=0,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 f*x;  
}
int n,m;
int a[MAXN],b[MAXN];
typedef struct node{
	int pos,x,y;
}node;
node d1[MAXN],d2[MAXN];
int p[MAXN],flag[NM];
typedef struct Node{
	int l,r,t,id;
	friend bool operator<(Node aa,Node bb){
		if(p[aa.l]==p[bb.l]&&p[aa.r]==p[bb.r]) return aa.t<bb.t;
		else if(p[aa.l]==p[bb.l]) return p[aa.r]<p[bb.r];
		else return p[aa.l]<p[bb.l];
	}
}Node;
Node que[MAXN];
int ans[MAXN],ans1;
void join(int l,int r,int pos){
	if(l<=d1[pos].pos&&d1[pos].pos<=r){
		flag[d1[pos].x]--;
		if(!flag[d1[pos].x])ans1--;
		flag[d1[pos].y]++;
		if(flag[d1[pos].y]==1)ans1++;
	}
	a[d1[pos].pos]=d1[pos].y;
}
void erase(int l,int r,int pos){
	if(l<=d2[pos].pos&&d2[pos].pos<=r){
		flag[d2[pos].x]--;
		if(!flag[d2[pos].x])ans1--;
		flag[d2[pos].y]++;
		if(flag[d2[pos].y]==1)ans1++;		
	}
	a[d2[pos].pos]=d2[pos].y;
}
int main(){
	n=read(),m=read();int sz=(int)pow(n,2.0/3);
	for(int i=1;i<=n;i++)p[i]=(i-1)/sz+1;
	inc(i,1,n)a[i]=read(),b[i]=a[i];
	int t=0,pos,vul;char ch;int cnt=0;
	for(int i=1;i<=m;i++){
		scanf(" %c",&ch);
		if(ch=='Q'){
			que[++cnt].l=read();que[cnt].r=read();que[cnt].id=i;que[cnt].t=t;
		}
		else{
			t++;pos=read(),vul=read();
			d1[t].pos=pos;d1[t].x=b[pos];d1[t].y=vul;
			d2[t].pos=pos;d2[t].x=vul;d2[t].y=b[pos];
			b[pos]=vul;
		}
		ans[i]=-1;
	}
	sort(que+1,que+cnt+1);
	int L=1,R=0,T=0;ans1=0;
	for(int i=1;i<=cnt;i++){
		while(que[i].t<T){
			erase(L,R,T);T--;
		}
		while(que[i].t>T){
			T++;join(L,R,T);
		}
		while(que[i].l>L){
			flag[a[L]]--;
			if(!flag[a[L]])ans1--;
			L++;
		}
		while(que[i].l<L){
			L--;flag[a[L]]++;
			if(flag[a[L]]==1)ans1++;
		}
		while(que[i].r<R){
			flag[a[R]]--;
			if(!flag[a[R]])ans1--;
			R--;
		}
		while(que[i].r>R){
			R++;flag[a[R]]++;
			if(flag[a[R]]==1)ans1++;
		}
		ans[que[i].id]=ans1;
	}
	for(int i=1;i<=m;i++)if(ans[i]>=0)printf("%d\n",ans[i]);
	return 0;
}

  

posted @ 2018-05-17 01:06  wang9897  阅读(143)  评论(0编辑  收藏  举报