记录编号 257628 评测结果 AAAAAAAAAA
题目名称 [NOI 2005]维护数列 最终得分 100
用户昵称 GravatarSky_miner 是否通过 通过
代码语言 C++ 运行时间 4.610 s
提交时间 2016-05-02 14:47:54 内存使用 28.93 MiB
显示代码纯文本
#include<cstdio>
#include<iostream>
using namespace std;
#define LL(x) (ch[x][0])
#define RR(x) (ch[x][1])
#define Kt (ch[ ch[rt][1] ][0])
const int INF = 0x7fffffff ;
const int maxn = 500000 + 100;
int a[maxn];
struct SplayTree{
	int rt,top1,top2;
	int pre[maxn],sz[maxn],ch[maxn][2],stk[maxn],que[maxn];
	//  前驱      节点大小  左右儿子      栈       队列 
	int same[maxn],flag[maxn],valu[maxn];
	int flip[maxn],sum[maxn],lmx[maxn],rmx[maxn],mx[maxn];//辅助数组 

	void addNode(int pos,int &x,int f){//添加新节点 
		if(top2) x=stk[--top2];
		else x=++top1;

		LL(x)=RR(x)=0; pre[x]=f;
		flag[x]=flip[x]=0;
		valu[x]=a[pos];
		sum[x]=lmx[x]=rmx[x]=mx[x]=-INF;
	}
	inline void iswap(int x){
		if(x==0)return;
		flip[x]^=1;
		swap(LL(x),RR(x));
		swap(lmx[x],rmx[x]);
	}
	inline void toSame(int x,int c){
		if(x==0) return;
		flag[x]=1,same[x]=c;
		valu[x]=c,sum[x]=sz[x]*c;
		lmx[x]=rmx[x]=mx[x]=max(sum[x],valu[x]);
	}
	void PushDown(int x){
		if(x==0) return;
		if(flip[x]){
			iswap(LL(x)); iswap(RR(x));
			flip[x]=0;
		}
		if(flag[x]){
			toSame(LL(x),same[x]);
			toSame(RR(x),same[x]);
			flag[x]=0;
		}
	}
	void PushUp(int x){//节点信息更新 
		sz[x]=1+sz[LL(x)]+sz[RR(x)];

		sum[x]=valu[x]+sum[LL(x)]+sum[RR(x)];
		mx[x]=lmx[x]=rmx[x]=-INF;

		lmx[x]=max(lmx[LL(x)],sum[LL(x)]+valu[x]+max(0,lmx[RR(x)]));
		rmx[x]=max(rmx[RR(x)],sum[RR(x)]+valu[x]+max(0,rmx[LL(x)]));

		mx[x]=max(mx[LL(x)],mx[RR(x)]);
		mx[x]=max(mx[x],valu[x]+max(0,rmx[LL(x)])+max(0,lmx[RR(x)]));
	}
	inline void Link(int x,int y,int f){//Link不用解释了吧 
		pre[x]=y; ch[y][f]=x;
	}
	inline void Rotate(int x,int f){//0表示左旋,1表示右旋
		int y=pre[x],z=pre[y];

		PushDown(y); PushDown(x);

		Link(ch[x][f],y,!f);
		Link(x,z,RR(z)==y);
		Link(y,x,f);

		PushUp(y);
	}
	inline void Splay(int x,int goal){//将节点x旋转到goal下面
		while(pre[x]!=goal){
			int y=pre[x],z=pre[y];
			int cx=(LL(y)==x),cy=(LL(z)==y);

			if(z==goal) Rotate(x,cx);
			else{
				if(cx==cy) Rotate(y,cy);
				else Rotate(x,cx);
				Rotate(x,cy);
			}
		}
		PushUp(x);
		if(goal==0) rt=x;
	}
	inline void Select(int K,int goal){//将第K个数旋转到goal下面。
		int x=rt;
		PushDown(x);
		while(sz[LL(x)]!=K){
			if(K<sz[LL(x)]) x=ch[x][0];
			else K-=sz[LL(x)]+1,x=ch[x][1];
			PushDown(x);
		}
		Splay(x,goal);
	}
	void Erase(int x){//删除以x为根的子树
		int father=pre[x];
		int head=0,tail=0;
		for(que[tail++]=x;head<tail;head++){
			stk[top2++]=que[head];
			if(LL(que[head])) que[tail++]=LL(que[head]);
			if(RR(que[head])) que[tail++]=RR(que[head]);
		}
		ch[father][ RR(father)==x ]=0;
	}
	void Insert(){//插入一段区间
		int pos,tot;
		scanf("%d%d",&pos,&tot);

		for(int i=1;i<=tot;i++) scanf("%d",&a[i]);

		Select(pos,0), Select(pos+1,rt);
		build(1,tot,Kt,ch[rt][1]);
		Splay(ch[rt][1],0);
	}
	void Delete(){//删除一段区间
		int pos,tot;
		scanf("%d%d",&pos,&tot);

		Select(pos-1,0), Select(pos+tot,rt);

		Erase(Kt);

		Splay(ch[rt][1],0);
	}
	void MakeSame(){//将一段区间内的值全部变成C
		int pos,tot,c;
		scanf("%d%d%d",&pos,&tot,&c);

		Select(pos-1,0), Select(pos+tot,rt);

		toSame(Kt,c);
		Splay(ch[rt][1],0);
	}
	void Reverse(){//将一段区间进行旋转
		int pos,tot;
		scanf("%d%d",&pos,&tot);

		Select(pos-1,0), Select(pos+tot,rt);
		iswap(Kt);
		Splay(ch[rt][1],0);
	}
	void GetSum(){//求一段区间和
	
		int pos,tot;
		scanf("%d%d",&pos,&tot);

		Select(pos-1,0), Select(pos+tot,rt);

		printf("%d\n",sum[Kt]);
	}
	void MaxSum(){//求出子区间和的最大值。
	
		Splay(1,0);
		Splay(2,1);
		printf("%d\n",mx[Kt]);
	}
	void build(int l,int r,int &x,int f){//建树
	
		if(l>r) return;

		int mid=l+r >> 1;
		addNode(mid,x,f);
		build(l,mid-1,LL(x),x);
		build(mid+1,r,RR(x),x);
		PushUp(x);
	}

	void init(int st,int ed){//初始化
	
		rt=top1=top2=0;
		sz[0]=pre[0]=LL(0)=RR(0)=0;

		lmx[0]=rmx[0]=mx[0]=-INF;

		addNode(0,rt,0); addNode(0,RR(rt),rt);

		build(st,ed,Kt,RR(rt));
		PushUp(RR(rt)); PushUp(rt);
	}
}Sky_miner;
int main(){
	freopen("seq2005.in","r",stdin);
	freopen("seq2005.out","w",stdout);
	int n,m;scanf("%d%d",&n,&m);
	a[0] = -INF;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	Sky_miner.init(1,n);
	char buf[100];
	for(int i=0;i<m;i++){
		scanf("%s",buf);
		if(buf[0]=='I') Sky_miner.Insert();
		else if(buf[0]=='D') Sky_miner.Delete();
		else if(buf[0]=='M'){
			if(buf[2]=='K') Sky_miner.MakeSame();
			else Sky_miner.MaxSum();
		}
		else if(buf[0]=='R') Sky_miner.Reverse();
		else Sky_miner.GetSum();
	}
	return 0;
}