[NOI2005] 维护数列


link

Splay维护序列的一个较为高级的实例,其它没什么,调得挺顺利的也没什么好说的,除了脑残一下wa#3以外其它都还好。需要告诫后人的是一定要注意摒弃那两个哨兵点,不然会死得很惨。

#include
//#define zczc
const int N=500010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}
inline int op(){
	char w[10];scanf("%s",w);
	switch(w[0]){
		case 'I':return 1;break;//insert
		case 'D':return 2;break;//delete
		case 'M':return w[2]=='K'?3:6;break;//same&max_sum
		case 'R':return 4;break;//reverse
		case 'G':return 5;break;//get_sum
	}
}
inline int min(int s1,int s2){
	return s1r)return 0;int x=kk();int mid=l+r>>1;
	t[x].data=a[mid];t[x].size=1;t[x].f=ff;
	lc=build(l,mid-1,x);rc=build(mid+1,r,x);
	pushup(x);return x;
}
inline void link(int x,int kk,int y){
	t[x].ch[kk]=y;t[y].f=x;return;
}
inline void rotate(int x){
	int y=t[x].f;int z=t[y].f;int kk=x==t[y].ch[1];
	link(z,t[z].ch[1]==y,x);
	link(y,kk,t[x].ch[kk^1]);
	link(x,kk^1,y);pushup(y);pushup(x);return;
}
inline void splay(int x,int rt){
	while(t[x].f^rt){
		int y=t[x].f;int z=t[y].f;
		if(z^rt)(t[z].ch[1]==y)^(t[y].ch[1]==x)?rotate(x):rotate(y);rotate(x);
	}if(rt==0)root=x;
}
inline int find(int val){
	int x=root;
	while(x){
		pushdown(x);
		if(val<=t[lc].size)x=lc;
		else{
			val-=t[lc].size+1;
			if(!val)return x;
			x=rc;
		}
	}
}
inline void dell(int x){
	if(!x)return;dell(lc);dell(rc);del(x);
}
inline void move(int pl,int pr){
	splay(pl,0);splay(pr,pl);return;
}
inline void repush(int pl,int pr){
	pushup(pr);pushup(pl);return;
}
inline void dfs(int x){
	if(!x)return;
	if(x==root)printf("______________\n");
	printf("%d %d %d %d&%d\n",x,t[x].data,t[x].size,lc,rc);dfs(lc);dfs(rc);
	if(x==root)printf("______________\n");
	return;
}
#undef lc
#undef rc

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
	#endif
	
	read(m);read(n);
	for(int i=1;i<=m;i++)read(a[i+1]);
	root=build(1,m+2,root);
	int l,r,num,data,pl,pr;
	while(n--){
		switch(op()){
			case 1:
				read(l);read(num);l++;m+=num;
				for(int i=1;i<=num;i++)read(a[i]);
				move(pl=find(l),pr=find(l+1));
				t[pr].ch[0]=build(1,num,pr);repush(pl,pr);
				break;
			case 2:
				read(l);read(num);m-=num;
				move(pl=find(l),pr=find(l+num+1));
				dell(t[pr].ch[0]);t[pr].ch[0]=0;repush(pl,pr);
				break;
			case 3:
				read(l);read(num);read(data);
				move(pl=find(l),pr=find(l+num+1));
				pushnows(t[pr].ch[0],data);repush(pl,pr);
				break;
			case 4:
				read(l);read(num);
				move(pl=find(l),pr=find(l+num+1));
				pushnowa(t[pr].ch[0]);repush(pl,pr);
				break;
			case 5:
				read(l);read(num);
				move(pl=find(l),pr=find(l+num+1));
				printf("%d\n",t[t[pr].ch[0]].sum);repush(pl,pr);
				break;
			case 6:
				l=1,r=m+2;move(pl=find(l),pr=find(r));
				printf("%d\n",t[t[pr].ch[0]].msum);
				break;
		}
	}
	
	return 0;
}

/*
1 insert
2 delete
3 same
4 reverse
5 get_sum
6 get_max
*/