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管理员要的数据本地的测试中也过了
个人感觉代码应该没问题
哦还附带赠送数据生成器
自己可以调数据生成的大小,我这个只有10个数,不过过几百组数据的话应该就没问题了
做法个人感觉已经说烂了,论文中说的很细
每个节点维护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; }
相关文章推荐
- BZOJ 1500([NOI2005]维修数列-Splay的数列维护)
- 维护数列 洛谷2042 bzoj1500 NOI2005
- BZOJ1500: [NOI2005]维修数列 Splay维护序列
- Splay 模板【NOI2005】 bzoj1500 维修数列
- BZOJ 1500: [NOI2005]维修数列( splay )
- BZOJ1500 维护数列 treap实现
- Bzoj 1500 维护数列
- 洛谷.2042.[NOI2005]维护数列(Splay)
- bzoj1500维修数列splay
- 【BZOJ1500】[NOI2005]维修数列【Splay】
- 【bzoj1500】[NOI2005]维修数列 Splay
- BZOJ1500: [NOI2005]维修数列 Splay
- [bzoj1500][NOI2005]维修数列 splay大模板
- 【BZOJ 1500】 维修数列|Splay
- NOI 2005 BZOJ 1500 维护数列
- BZOJ 1500 [NOI 2005] 维修数列 (splay 模板)
- BZOJ 1500 NOI2005 维修数列 Splay
- BZoj 1500 [NOI2005]维修数列 (Splay 模板)
- BZOJ 1500 维护(维修?)数列
- bzoj 1500: [NOI2005]维修数列 -- splay