您的位置:首页 > 运维架构

splay BZOJ1500 NOI2005 维护数列

2014-04-11 17:16 218 查看
传说中的splay神题,其实个人感觉还行,算是上个时代的数据结构神题吧,现在都流行各种分治,各种神转化+朴素线段树,或者动态XXX函数式XXX

做法个人感觉已经说烂了,论文中说的很细

每个节点维护size,father,child【2】(两个孩子)

标记要维护的是same,SameVal,res,MaxL,MaxR,MaxM,sum

分别是是否修改为一样的值,修改的值,是否翻转,这个区间从左边开始的最大连续值,从右边开始的最大值,整个区间的最长子序列,还有这个序列的和

然后就是维护了 

注意down(向下传标记)的时候先传same再传res

如果有same的话就不用传res了,这个不难理解吧

剩下的个人感觉没什么说的必要了

都是splay维护区间问题的经典问题

如果没写过splay维护区间问题的话

想入门看这里

哦对有个小插曲,个人的代码在bzoj挂了。。。原因不知道。。。

但是代码在BSOJ上AC了,时间是3s多一点

我自己问bzoj管理员要的数据本地的测试中也过了

个人感觉代码应该没问题

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAX 2850003
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define inf 0x7fffffff/4

using namespace std;

int pos,total,tot=0,root;
int size[MAX],child[2][MAX],res[MAX];
int same[MAX],value[MAX],a[MAX],b[MAX],sum[MAX];
int MaxL[MAX],MaxR[MAX],MaxM[MAX],father[MAX],SameVal[MAX];

void down(int x)
{
if(!x)
return;
if(same[x])
{
same[x]=res[x]=0;

value[x]=SameVal[x];
sum[x]=SameVal[x]*size[x];

if(value[x]<0)
MaxL[x]=MaxR[x]=MaxM[x]=value[x];
else
MaxL[x]=MaxR[x]=MaxM[x]=sum[x];

same[child[0][x]]=same[child[1][x]]=1;
SameVal[child[0][x]]=SameVal[child[1][x]]=SameVal[x];
}
if(res[x])
{
/*if(child[0][x])
res[child[0][x]]^=1;
if(child[1][x])
res[child[1][x]]^=1;
swap(MaxL[child[0][x]],MaxR[child[1][x]]);
swap(child[0][x],child[1][x]);
res[x]=0;*/
res[x]=0;
swap(child[0][x],child[1][x]);
swap(MaxL[x],MaxR[x]);

res[child[0][x]]=!res[child[0][x]];
res[child[1][x]]=!res[child[1][x]];
}
}

void up(int x)
{
if(!x)
return;
down(child[0][x]);
down(child[1][x]);

size[x]=1+size[child[0][x]]+size[child[1][x]];
sum[x]=sum[child[0][x]]+value[x]+sum[child[1][x]];

//l
MaxL[x]=MaxL[child[0][x]];
MaxL[x]=max(MaxL[x],max(sum[child[0][x]]+value[x],sum[child[0][x]]+value[x]+MaxL[child[1][x]]));

//r
MaxR[x]=MaxR[child[1][x]];
MaxR[x]=max(MaxR[x],max(sum[child[1][x]]+value[x],sum[child[1][x]]+value[x]+MaxR[child[0][x]]));

//m
MaxM[x]=max(value[x],MaxR[child[0][x]]+value[x]+MaxL[child[1][x]]);
MaxM[x]=max(MaxM[x],max(MaxM[child[0][x]],MaxM[child[1][x]]));
MaxM[x]=max(MaxM[x],max(value[x]+MaxR[child[0][x]],value[x]+MaxL[child[1][x]]));
MaxM[x]=max(MaxM[x],MaxL[child[1][x]]+value[x]+MaxR[child[0][x]]);
return;
}

void build(int &x,int l,int r)
{
if(l>r)
{
x=0;
return;
}
x=++tot;
int mid=(l+r)>>1;
value[x]=sum[x]=a[mid];
same[x]=0;
res[x]=0;
MaxL[x]=MaxR[x]=MaxM[x]=SameVal[x]=-inf;
build(child[0][x],l,mid-1);
build(child[1][x],mid+1,r);
if(child[0][x])
father[child[0][x]]=x;
if(child[1][x])
father[child[1][x]]=x;
up(x);
return ;
}

void Insert(int &x,int l,int r)
{
if(l>r)
{
x=0;
return;
}
int mid=(l+r)>>1;
x=++tot;
value[x]=sum[x]=b[mid];
same[x]=res[x]=0;
MaxL[x]=MaxR[x]=MaxM[x]=SameVal[x]=-inf;
Insert(child[0][x],l,mid-1);
Insert(child[1][x],mid+1,r);
if(child[0][x])
father[child[0][x]]=x;
if(child[1][x])
father[child[1][x]]=x;
up(x);
}

int select(int k)
{
int t=root;
while(1)
{
down(t);
//	printf("fuck\n");
if(size[child[0][t]]+1==k)
return t;
if(size[child[0][t]]>=k)
t=child[0][t];
else
k-=size[child[0][t]]+1,t=child[1][t];
}
return -1;
}

void rotate(int p)
{
int q=father[p],y=father[q],x=(child[1][q]==p);
down(q);
down(p);
down(child[0][p]),down(child[1][p]),down(child[x^1][p]);

father[child[x][q]=child[x^1][p]]=q;
father[child[x^1][p]=q]=p;
father[p]=y;
if(y)
child[child[1][y]==q][y]=p;

up(q);
return;
}

void splay(int x,int aim=0)
{
down(x);
for(int y;(y=father[x])!=aim;rotate(x))
if(father[y]!=aim)
{
if((child[0][y]==y)==(child[0][y]==x))
rotate(y);
else
rotate(x);
}//*/
/*for(int y;(y=father[x])!=aim;)
{
int z;
if((z=father[y])==aim)
rotate(x);
else
if((child[1][y]==x)==(child[1][z]==y))
rotate(y),rotate(x);
else
rotate(x),rotate(x);
}*/
if(!aim)
root=x;
up(x);
return;
}

void debug()
{
printf("--------------------debug------------------------\n");
rep(i,1,tot)
printf("%d %d %d\n",i,select(i),value[select(i)]);
printf("i fa child_l   child_r size MaxL MaxR MaxM       val   sum   res same SameVal\n");
rep(i,1,tot)
printf("%d %d   %d          %d     %d  %d %d %d            %d     %d  %d %d %d\n",i,father[i],child[0][i],child[1][i],size[i],MaxL[i],MaxR[i],MaxM[i],value[i],sum[i],res[i],same[i],SameVal[i]);
printf("--------------------debug------------------------\n");
}

void insert()
{
splay(select(pos+1));
splay(select(pos+2),root);
Insert(child[0][child[1][root]],1,total);
if(child[0][child[1][root]])
father[child[0][child[1][root]]]=child[1][root];
up(child[1][root]);
up(root);
return ;
}

void Delete()
{
splay(select(pos));
splay(select(pos+total+1),root);
//	debug();
child[0][child[1][root]]=0;
splay(child[1][root]);
//	up(child[1][root]);
//	up(root);
//	tot-=total;
return;
}

void make_same(int Pos,int Total,int ind)
{
splay(select(Pos));
splay(select(Pos+Total+1),root);

same[child[0][child[1][root]]]=1;
SameVal[child[0][child[1][root]]]=ind;

splay(child[0][child[1][root]],0);
//	down(child[0][child[1][root]]);
//	up(child[1][root]);
//	up(root);
return;
}

void reserve()
{
splay(select(pos));
splay(select(pos+total+1),root);
res[child[0][child[1][root]]]^=1;

splay(child[0][child[1][root]],0);
}

int ask_num()
{
//printf("ask %d %d %d %d\n",pos,total,select(pos),select(pos+1+total));
splay(select(pos));
splay(select(pos+1+total),root);
down(child[0][child[1][root]]);
return sum[child[0][child[1][root]]];
}

int get_max_num()
{
down(root);
up(root);
return MaxM[root];
}

void get(int &x)
{
int ret=0;
char ch;
while(ch=getchar())
if((ch>='0'&&ch<='9')||ch=='-')
break;
bool f=(ch=='-');
if(f)
ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar())
ret=ret*10+ch-'0';
x=f?-ret:ret;
return;
}

int main()
{
MaxL[0]=MaxR[0]=MaxM[0]=-inf;
int n,m;
scanf("%d%d",&n,&m);
a[1]=a[n+2]=-inf;
rep(i,2,n+1)
scanf("%d",&a[i]);
n+=2;
build(root,1,n);
while(m--)
{
char s[300];
scanf("%s",s);
switch (s[0])
{
case 'I':
get(pos);
get(total);
rep(i,1,total)
get(b[i]);
insert();
break;
case 'D':
get(pos);
get(total);
Delete();
break;
case 'M':
{
if(s[2]=='K')
{
int c;
get(pos),get(total),get(c);
make_same(pos,total,c);
break;
}
else
{
printf("%d\n",get_max_num());
break;
}
break;
}
case 'R':
get(pos),get(total);
reserve();
break;
case 'G':
get(pos),get(total);
printf("%d\n",ask_num());
break;
}
//debug();
}
return 0;
}


哦还附带赠送数据生成器

自己可以调数据生成的大小,我这个只有10个数,不过过几百组数据的话应该就没问题了

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#define mod 10
#define del 10

using namespace std;

int main()
{
freopen("1500.in","w",stdout);
srand((unsigned)time(0));
int n=10,m=6,no;

string s[10];
s[1]="INSERT";s[2]="DELETE";
s[3]="MAKE-SAME";s[4]="RESERVE";
s[5]="GET-SUM";s[6]="MAX-SUM";
printf("%d %d\n",n,m);
for(int i=1;i<=n;i++)
no=rand()%mod-del,printf("%d\n",no);
while(m--)
{
int con=rand()%6+1;
if(con==1)
{
cout<<s[1]<<' ';
int a=n,b=n;
while(a+b>n)
a=rand()%n+1,b=rand()%n+1;
printf("%d %d",a,b);
int now;
while(b--)
now=rand()%mod-del,printf(" %d");
printf("\n");
}
else
if(con==2||con==4||con==5)
{
cout<<s[con]<<' ';
int a=n,b=n;
while(a+b>n)
a=rand()%n+1,b=rand()%n+1;
printf("%d %d\n",a,b);
}
else
if(con==3)
{
cout<<s[3]<<' ';
int a=n,b=n;
while(a+b>n)
a=rand()%n+1,b=rand()%n+1;
int now=rand()%mod-del;
printf("%d %d %d\n",a,b,now);
}
else
if(con==6)
cout<<s[6]<<"\n";
}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: