记录编号 192449 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2011]数颜色 最终得分 100
用户昵称 Gravatarstdafx.h 是否通过 通过
代码语言 C++ 运行时间 0.825 s
提交时间 2015-10-11 06:30:34 内存使用 12.03 MiB
显示代码纯文本
//algorithm::segtree with treap + treap   --by stdafx

#define lson l,m,t
#define rson m+1,r,t|1

#define MAXN 10010UL
#define MAXL 10UL

#include <cstdio>
#include <ctime>
#include <cstdlib>

struct Treap_Node{
	Treap_Node *left,*right;
	int val,fix,s;
	Treap_Node(){
		left=NULL,right=NULL;
	}
};

Treap_Node *tree[MAXN<<2],*color_tree[MAXN*100];
int n,m,seq[MAXN],Ans,Check_Val,posl,posr,color_pre[MAXN*100],pre[MAXN],update_pos,color_next[MAXN*100],Next[MAXN],before_val,after_val;
char query[MAXL];

inline int in(){
	int x=0,c=getchar();
	while(c<'0'||c>'9') c=getchar();
	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+c-48;
	return x;
}

inline void Update_Treap_Node(Treap_Node *&p){
	if(!p) return;
	p->s=1;
	if(p->left) p->s+=p->left->s;
	if(p->right) p->s+=p->right->s;
	return;
}

inline void LeftTurn(Treap_Node *&a){
	Treap_Node *b=a->right;
	a->right=b->left;b->left=a;a=b;
	Update_Treap_Node(b->left);
	return;
}

inline void RightTurn(Treap_Node *&a){
	Treap_Node *b=a->left;
	a->left=b->right;b->right=a;a=b;
	Update_Treap_Node(b->right);
	return;
}

int Find(Treap_Node *p,int val){
	if(!p) return 0;
	if(p->val<val){
		int tmp=Find(p->right,val)+1;
		if(p->left) return p->left->s+tmp;
		else return tmp;
	}
	else return Find(p->left,val);
}

void Insert(Treap_Node *&p,int val){
	if(!p){
		p=new Treap_Node();
		p->val=val;p->fix=rand();p->s=1;
	}
	else if(val<=p->val){
		Insert(p->left,val);
		if((p->left->fix)<(p->fix)) RightTurn(p);
	}
	else{
		Insert(p->right,val);
		if((p->right->fix)<(p->fix)) LeftTurn(p);
	}
	Update_Treap_Node(p);
	return;
}

void Delete(Treap_Node *&p,int val){
	if(val==p->val){
		if((!p->left)||(!p->right)){
			Treap_Node *t=p;
			if(p->left) p=p->left;
			else p=p->right;
			delete t;
		}
		else{
			if((p->left->fix)<(p->right->fix)) RightTurn(p),Delete(p->right,val);
			else LeftTurn(p),Delete(p->left,val);
		}
	}
	else if(val<p->val) Delete(p->left,val);
	else Delete(p->right,val);
	Update_Treap_Node(p);
	return;
}

void Build(int l,int r,int rt){
	for(int i=l;i<=r;i++){
		Insert(tree[rt],pre[i]);
	}
	if(l==r) return;
	int m=(l+r)>>1,t=rt<<1;
	Build(lson);Build(rson);
	return;
}

void Update(int l,int r,int rt){
	Delete(tree[rt],before_val);
	Insert(tree[rt],after_val);
	if(l==r) return;
	int m=(l+r)>>1,t=rt<<1;
	if(update_pos<=m) Update(lson);
	if(update_pos>m) Update(rson);
	return;
}

void Query(int l,int r,int rt){
	if(posl<=l&&posr>=r){
		Ans+=Find(tree[rt],Check_Val);
		return;
	}
	int m=(l+r)>>1,t=rt<<1;
	if(posl<=m) Query(lson);
	if(posr>m) Query(rson);
	return;
}

inline void QUERY(int L,int R){
	Ans=0;Check_Val=L;
	posl=L;posr=R;
	Query(1,n,1);
	printf("%d\n",Ans);
	return;
}

int find_Last(Treap_Node *p,int val){
	if(!p) return 0;
	if(p->val>val){
		int find_l=find_Last(p->left,val);
		if(find_l) return find_l;
		else return p->val;
	}
	return find_Last(p->right,val);
}

int find_Smaller(Treap_Node *p,int val){
	if(!p) return 0;
	if(p->val<val){
		int find_l=find_Smaller(p->right,val);
		if(find_l) return find_l;
		else return p->val;
	}
	return find_Smaller(p->left,val);
}

inline void MODIFY(int now_pos,int new_color){
	if(seq[now_pos]==new_color) return;
	int r_color=seq[now_pos];
	Delete(color_tree[r_color],now_pos);
	if(pre[now_pos]) Next[pre[now_pos]]=Next[now_pos];
	if(Next[now_pos]){
		int next_r_pos=Next[now_pos];
		pre[next_r_pos]=pre[now_pos];
		if(pre[now_pos]) Next[pre[now_pos]]=next_r_pos;
		update_pos=next_r_pos;
		before_val=now_pos;after_val=pre[now_pos];Update(1,n,1);
	}
	int new_after=find_Last(color_tree[new_color],now_pos),ready_update=0;
	if(new_after){
		if(pre[new_after]) Next[pre[new_after]]=now_pos,ready_update=pre[new_after];
		update_pos=new_after;before_val=pre[new_after];after_val=now_pos;Update(1,n,1);
		pre[new_after]=now_pos;
	}
	if(!ready_update) ready_update=find_Smaller(color_tree[new_color],now_pos);
	Next[ready_update]=now_pos;
	Next[now_pos]=new_after;
	before_val=pre[now_pos];
	pre[now_pos]=ready_update;
	update_pos=now_pos;after_val=ready_update;Update(1,n,1);
	seq[now_pos]=new_color;
	Insert(color_tree[new_color],now_pos);
	return;
}

int main(){
	freopen("nt2011_color.in","r",stdin);freopen("nt2011_color.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		seq[i]=in();pre[i]=color_pre[seq[i]];color_pre[seq[i]]=i;Insert(color_tree[seq[i]],i);
	}
	for(int i=n;i>0;i--){
		Next[i]=color_next[seq[i]];color_next[seq[i]]=i;
	}
	Build(1,n,1);
	for(int i=1,a,b;i<=m;i++){
		scanf("%s",query);a=in();b=in();
		if(query[0]=='Q') QUERY(a,b);
		else MODIFY(a,b);
	}
	return 0;
}