记录编号 90969 评测结果 AAAAAAAAAA
题目名称 [NOI 2005]维护数列 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 3.486 s
提交时间 2014-03-11 13:19:07 内存使用 11.76 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int SIZEN=3000010,INF=0x7fffffff/2;
class SPLAYTREE{
public:
	class NODE{
	public:
		int key,sum,smx,lmx,rmx,size;
		bool rev,same;//是否翻转,是否全一样
		NODE *lc,*rc,*f;//两个儿子和父亲
		NODE(int k){key=sum=smx=lmx=rmx=k,size=1,rev=same=0;}
		NODE(){NODE(0);}
	}*Nil,*left,*right,*Root;
	NODE* newNODE(int key){
		NODE *T=new NODE(key);
		T->lc=T->rc=T->f=Nil;
		return T;
	}
	SPLAYTREE(){
		Nil=new NODE(-INF);
		Nil->lc=Nil->rc=Nil->f=Nil;
		Nil->sum=Nil->size=0;//建立虚拟空节点
		left=new NODE(-INF),right=new NODE(-INF);
		left->lc=left->rc=left->f=Nil;
		right->lc=right->rc=right->f=Nil;
		left->sum=right->sum=0;
		left->rc=right,right->f=left;
		(left->size)++;Root=left;//建立边界节点
	}
	void pushdown(NODE *T){
		if(T->rev){
			swap(T->lc,T->rc);
			swap(T->lmx,T->rmx);
			T->lc->rev^=1,T->rc->rev^=1;
			T->rev=0;
		}
		if(T->same){
			T->same=0;T->lc->same=T->rc->same=1;
			T->lc->key=T->rc->key=T->key;
			T->lmx=T->rmx=T->sum=T->smx=T->key*T->size;
			if(T->key<0) T->lmx=T->rmx=T->smx=T->key;//此时的最大值是只取一项
		}
	}
	void update(NODE *T){
		T->size=T->lc->size+T->rc->size+1;
		T->sum=T->lc->sum+T->rc->sum+T->key;
		T->lmx=max(T->lc->lmx,T->lc->sum+T->key+max(0,T->rc->lmx));
		T->rmx=max(T->rc->rmx,T->rc->sum+T->key+max(0,T->lc->rmx));
		T->smx=max(T->lc->smx,T->rc->smx);//情况①:在左右子树中
		T->smx=max(T->smx,T->key+max(T->lc->rmx,0)+max(T->rc->lmx,0));//情况②:这个点向左右延伸或不延伸
	}
	void zig(NODE *T){//右旋
		NODE *P=T->f,*rson=T->rc;
		pushdown(P->rc);pushdown(T->lc);pushdown(T->rc);//旋转之前先下压标记
		if(Root==P) Root=T;//修改在更前的父结点处的悬挂方式
		else (P->f->lc==P)?(P->f->lc=T):(P->f->rc=T);
		T->f=P->f;P->f=T;P->lc=rson;T->rc=rson->f=P;//修改三个子节点的悬挂方式
		update(P);
	}
	void zag(NODE *T){//左旋
		NODE *P=T->f,*lson=T->lc;
		pushdown(P->lc);pushdown(T->lc);pushdown(T->rc);
		if(Root==P) Root=T;
		else (P->f->lc==P)?(P->f->lc=T):(P->f->rc=T);
		T->f=P->f;P->f=T;P->rc=lson;T->lc=lson->f=P;
		update(P);
	}
	void splay(NODE *ANC,NODE *t){//把t旋转到ANC
		pushdown(t);//因为后面要改悬挂点,因此在这里push下去
		if(t==ANC){
			update(t);
			return;
		}
		bool reach=false;
		while(!reach){
			NODE *P=t->f;
			if(P==ANC) (P->lc==t)?zig(t):zag(t),reach=true;
			else{
				if(P->f==ANC) reach=true;
				if(P->f->lc==P) (P->lc==t)?zig(P):zag(t),zig(t);
				else (P->rc==t)?zag(P):zig(t),zag(t);
			}
		}
		update(t);
	}
	void select(NODE *ANC,int k){//将ANC子树中的第k项提到ANC的位置
		NODE *t=ANC;
		while(true){
			pushdown(t);
			if(k==t->lc->size+1){
				splay(ANC,t);
				return;
			}
			if(k<=t->lc->size) t=t->lc;
			else k-=t->lc->size+1,t=t->rc;
		}
	}
	void Insert(int pos,int a[],int k){//在pos后插入a[1]~a[k]
		select(Root,pos+1);select(Root->rc,1);
		NODE *t=newNODE(a[1]),*p=t,*q=t;
		for(int i=2;i<=k;i++) t=newNODE(a[i]),t->f=p,p->rc=t,p=t;
		Root->rc->lc=q;q->f=Root->rc;
		splay(Root,p);
	}
	void Delete(int pos,int tot){
		select(Root,pos),select(Root->rc,tot+1);
		Root->rc->lc=Nil;
		splay(Root,Root->rc);
	}
	void Reverse(int pos,int tot){
		select(Root,pos),select(Root->rc,tot+1);
		Root->rc->lc->rev^=1;splay(Root,Root->rc->lc);
	}
	void Makesame(int pos,int tot,int key){
		select(Root,pos);select(Root->rc,tot+1);
		Root->rc->lc->key=key;Root->rc->lc->same=true;
		splay(Root,Root->rc->lc);
	}
	int Getsum(int pos,int tot){
		select(Root,pos);select(Root->rc,tot+1);
		return Root->rc->lc->sum;
	}
	int Maxsum(void){return Root->smx;}
};
SPLAYTREE tree;
int N,M;
int a[SIZEN]={0};
void init(void){
	scanf("%d%d",&N,&M);
	for(int i=1;i<=N;i++) scanf("%d",&a[i]);
	tree.Insert(0,a,N);
}
void work(void){
	string cmd;
	int pos,tot,x;
	while(M--){
		cin>>cmd;
		if(cmd=="MAX-SUM"){
			printf("%d\n",tree.Maxsum());
			continue;
		}
		scanf("%d%d",&pos,&tot);
		if(cmd=="INSERT"){
			for(int i=1;i<=tot;i++) scanf("%d",&a[i]);
			tree.Insert(pos,a,tot);
		}
		else if(cmd=="DELETE") tree.Delete(pos,tot);
		else if(cmd=="MAKE-SAME"){
			scanf("%d",&x);
			tree.Makesame(pos,tot,x);
		}
		else if(cmd=="REVERSE") tree.Reverse(pos,tot);
		else if(cmd=="GET-SUM") printf("%d\n",tree.Getsum(pos,tot));
	}
}
int main(){
	freopen("seq2005.in","r",stdin);
	freopen("seq2005.out","w",stdout);
	init();
	work();
	return 0;
}