procedure2012
It's not worth it to know you're not worth it!

[关键字]:splay

[题目大意]:太麻烦了自己找题看吧。

//=============================================================================

[分析]:就是一些基本的splay操作。将一个区间[a,b]从splay树中取出来要先将a-1旋到根b+1旋到根的右子树,然后以根的右树的左树为根的子树就是区间[a,b]。每个splay树中的节点要保存:数值dat,子书大小size、sum区间和、maxsum最大子段和,mls从左开始连续的最大子段和,mrs同样;same是否要改为普通值,rev是否需翻转。同时为了免去NULL的判断,先新建一个新的null节点作为结束的标志,并提前在splay中加入两个节点一个在头一个在尾免去插入时对边界的的判断。首先说插入到a后面,其实就是插入到[a,a+1]中间,先将要插入的数列拍成一条链然后将a旋到根,a+1旋到根的右树,然后将这条链接到根的右树的左树。删除a以后的数字操作就是,旋转a到根,旋转b到根的右树,然后删掉根的右树的左树就行了。修改操作要记录个bool值判断是否要修改,如果需要修改就把bool值下传并维护sum数组为size*dat,如果改成了负值sum=修改的负值,maxsum、mls、mrs同理。翻转操作也需要一个bool,如果需要翻转就将左右子树和mls、mrs交换同时更改儿子bool值——取反。求和操作只要提取出[a,b]然后输出它所对应的sum值,求最大自序列和则要输出root的maxsum域。后两个操作知识提取值,但之前对于这两个操作需要的值得维护很重要。

[代码]:

View Code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=2850003;
const int MAXL=500001;
const int INF=100000000;

struct node
{
node *f,*c[2];
int size,dat,sum,maxsum,mls,mrs;
bool same,rev;
}SS[MAXN],*null,*root;
int n,m,SC,pos,tot,c;
int a[MAXL];
char s1[20];

node *New(int dat,node *f)
{
node *e=SS+ ++SC;
e->size=1;
e->f=f;
e->dat=e->sum=e->maxsum=e->mls=e->mrs=dat;
e->c[0]=e->c[1]=null;
e->same=e->rev=0;
return e;
}

void Update(node *v)
{
if (v==null) return;
v->size=v->c[0]->size+v->c[1]->size+1;
v->sum=v->c[0]->sum+v->c[1]->sum+v->dat;
v->mls=v->c[0]->mls;
v->mls=max(v->mls,v->c[0]->sum+v->dat);
v->mls=max(v->mls,v->c[0]->sum+v->dat+v->c[1]->mls);
v->mrs=v->c[1]->mrs;
v->mrs=max(v->mrs,v->c[1]->sum+v->dat);
v->mrs=max(v->mrs,v->c[1]->sum+v->dat+v->c[0]->mrs);
v->maxsum=v->dat;
v->maxsum=max(v->maxsum,v->c[0]->maxsum);
v->maxsum=max(v->maxsum,v->c[1]->maxsum);
v->maxsum=max(v->maxsum,v->c[0]->mrs+v->dat);
v->maxsum=max(v->maxsum,v->c[1]->mls+v->dat);
v->maxsum=max(v->maxsum,v->c[0]->mrs+v->dat+v->c[1]->mls);
}

void Push_down(node *v)
{
if (v==null) return;
if (v->same)
{
v->same=0;
v->c[0]->same=v->c[1]->same=1;
v->c[0]->dat=v->c[1]->dat=v->dat;
v->sum=v->maxsum=v->mls=v->mrs=v->dat*v->size;
if (v->dat<0)
v->maxsum=v->mls=v->mrs=v->dat;
}
if (v->rev)
{
v->rev=0;
swap(v->c[0],v->c[1]);
v->c[0]->rev^=1,v->c[1]->rev^=1;
swap(v->mls,v->mrs);
}
}

void Debug(node *v)
{
if (v==null) return;
Push_down(v);
Debug(v->c[0]);
printf("%d ",v->dat);
Debug(v->c[1]);
}

void Prepare()
{
SC=-1;
null=NULL;
null=New(-INF,NULL);
null->size=0;
root=New(-INF,null);
root->c[1]=New(-INF,root);
null->sum=root->sum=root->c[1]->sum=0;
Update(root);
}

void Rotate(node *x,int o)
{
node *y=x->f;
Push_down(x->c[0]),Push_down(x->c[1]),Push_down(y->c[!o]);
y->c[o]=x->c[!o];
y->c[o]->f=y;
x->f=y->f;
if (y->f->c[0]==y)
x->f->c[0]=x;
else
x->f->c[1]=x;
y->f=x;
x->c[!o]=y;
Update(y);
if (root==y) root=x;
}

void Splay(node *x,node *fa)
{
Push_down(x);
while (x->f!=fa)
{
if (x->f->f==fa)
{
if (x->f->c[0]==x)
Rotate(x,0);
else
Rotate(x,1);
}
else
if (x->f->f->c[0]==x->f)
{
if (x->f->c[0]==x)
Rotate(x->f,0),Rotate(x,0);
else
Rotate(x,1),Rotate(x,0);
}
else
if (x->f->c[1]==x)
Rotate(x->f,1),Rotate(x,1);
else
Rotate(x,0),Rotate(x,1);
}
Update(x);
}

void Select(int k,node *fa)
{
int temp;
node *t;
for (t=root;;)
{
Push_down(t);
//printf("%d %d\n",k,t->c[0]->size);
temp=t->c[0]->size;
if (temp+1==k) break;
if (k<=temp) t=t->c[0]; else k-=temp+1,t=t->c[1];
}
Splay(t,fa);
}

void Insert(int pos,int tot,int *a)
{
node *t,*z;
t=z=New(a[1],null);
for (int i=2;i<=tot;++i)
z=z->c[1]=New(a[i],z);
//printf("%d %d %d\n",root->size,root->c[0]->size,root->c[1]->size);
Select(pos+1,null);
Select(pos+2,root);
root->c[1]->c[0]=t;
t->f=root->c[1];
Splay(z,null);
}

void Delete(int pos,int tot)
{
Select(pos,null);
Select(pos+tot+1,root);
root->c[1]->c[0]=null;
Splay(root->c[1],null);
}

int GETSUM(int pos,int tot)
{
Select(pos,null);
Select(pos+tot+1,root);
//printf("%d\n",root->c[1]->c[0]->dat);
//printf("%d %d %d\n",root->c[1]->c[0]->size,root->c[1]->c[0]->dat,root->c[1]->c[0]->sum);
Push_down(root->c[1]->c[0]);
//Debug(root);
return root->c[1]->c[0]->sum;
}

void REVERSE(int pos,int tot)
{
Select(pos,null);
Select(pos+tot+1,root);
root->c[1]->c[0]->rev^=1;
Splay(root->c[1]->c[0],null);
}

void MAKESUM(int pos,int tot,int c)
{
Select(pos,null);
Select(pos+tot+1,root);
root->c[1]->c[0]->same=1;
//printf("%d\n",root->c[1]->c[0]->dat);
root->c[1]->c[0]->dat=c;
Splay(root->c[1]->c[0],null);
}

int MAXSUM()
{
Push_down(root);
Update(root);
return root->maxsum;
}

int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
Prepare();
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
Insert(0,n,a);
for (int i=1;i<=m;++i)
{
scanf("%s",s1);
if (s1[0]=='I')
{
scanf("%d%d",&pos,&tot);
for (int i=1;i<=tot;++i)
scanf("%d",&a[i]);
Insert(pos,tot,a);
//Debug(root);
//printf("\n");
}
if (s1[0]=='D')
{
scanf("%d%d",&pos,&tot);
Delete(pos,tot);
//Debug(root);
//printf("\n");
}
if (s1[0]=='M' && s1[2]=='K')
{
scanf("%d%d%d",&pos,&tot,&c);
MAKESUM(pos,tot,c);
//Debug(root);
//printf("\n");
}
if (s1[0]=='R')
{
scanf("%d%d",&pos,&tot);
REVERSE(pos,tot);
//Debug(root);
//printf("\n");
}
if (s1[0]=='G')
{
scanf("%d%d",&pos,&tot);
printf("%d\n",GETSUM(pos,tot));
}
if (s1[0]=='M' && s1[2]=='X')
printf("%d\n",MAXSUM());
}
return 0;
}



posted on 2012-03-30 22:42  procedure2012  阅读(584)  评论(0编辑  收藏  举报