BZOJ1500 [NOI2005]维修数列 splay
Posted tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ1500 [NOI2005]维修数列 splay相关的知识,希望对你有一定的参考价值。
原文链接http://www.cnblogs.com/zhouzhendong/p/8108676.html
题目传送门 - BZOJ1500
题意概括
Description
Input
输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初始时数列中数的个数,M表示要进行的操作数目。
第2行包含N个数字,描述初始时的数列。
以下M行,每行一条命令,格式参见问题描述中的表格。
任何时刻数列中最多含有500 000个数,数列中任何一个数字均在[-1 000, 1 000]内。
插入的数字总数不超过4 000 000个,输入文件大小不超过20MBytes。
Output
对于输入数据中的GET-SUM和MAX-SUM操作,向输出文件依次打印结果,每个答案(数字)占一行。
题解
splay乱维护就可以了。
维护:区间sum,左max,右max,区间max,size
这题要回收内存。
还有,不用开longlong,int可过。
还有,子列长度至少为1,那么就要把节点0的sum,Lmax,Rmax,Max全部赋值成-Inf
注意哨兵节点的安插。
代码
#include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> using namespace std; const int Inf=1e9; bool isd(char ch){ return \'0\'<=ch&&ch<=\'9\'; } int read(){ int res=0,f=1; char ch=getchar(); while (!isd(ch)&&ch!=\'-\') ch=getchar(); if (ch==\'-\') f=-1,ch=getchar(); while (isd(ch)) res=(res<<1)+(res<<3)+ch-48,ch=getchar(); return res*f; } const int S=500005; int n,m,a[S]; int total,root,st[S],top,Lmax[S],Rmax[S],sum[S],val[S],Max[S]; int fa[S],son[S][2],rev[S],cov[S],size[S]; void clear_node(int x,int v){ Lmax[x]=Rmax[x]=val[x]=sum[x]=Max[x]=v; rev[x]=0,cov[x]=-Inf,size[x]=1; fa[x]=son[x][0]=son[x][1]=0; } int new_node(int v){ int x=top?st[top--]:++total; clear_node(x,v); return x; } void pushup(int x){ if (!x) return; int ls=son[x][0],rs=son[x][1]; sum[x]=sum[ls]+val[x]+sum[rs]; size[x]=size[ls]+size[rs]+1; Lmax[x]=max(Lmax[ls],sum[ls]+val[x]+max(Lmax[rs],0)); Rmax[x]=max(Rmax[rs],sum[rs]+val[x]+max(Rmax[ls],0)); Max[x]=max(max(Max[ls],Max[rs]),max(Rmax[ls],0)+val[x]+max(Lmax[rs],0)); } void pushson(int x,int r,int c){ if (!x) return; if (r){ rev[x]^=1; swap(Lmax[x],Rmax[x]); swap(son[x][0],son[x][1]); } if (c>=-1000) Max[x]=Lmax[x]=Rmax[x]=max(sum[x]=c*size[x],cov[x]=val[x]=c),rev[x]=0; } void pushdown(int x){ int &ls=son[x][0],&rs=son[x][1],&r=rev[x],&c=cov[x]; pushson(ls,r,c); pushson(rs,r,c); r=0,c=-Inf; } void pushadd(int x){ if (fa[x]) pushadd(fa[x]); pushdown(x); } int wson(int x){ return son[fa[x]][1]==x; } void rotate(int x){ if (!fa[x]) return; int y=fa[x],z=fa[y],L=wson(x),R=L^1; if (z) son[z][wson(y)]=x; fa[x]=z,fa[y]=x,fa[son[x][R]]=y; son[y][L]=son[x][R],son[x][R]=y; pushup(y),pushup(x); } void splay(int x,int rt){ if (!x) return; if (!rt) root=x; pushadd(x); for (int y=fa[x];fa[x]!=rt;rotate(x),y=fa[x]) if (fa[y]!=rt) rotate(wson(x)==wson(y)?y:x); } int build(int pre,int L,int R){ if (L>R) return 0; int mid=(L+R)>>1; int rt=new_node(a[mid]); fa[rt]=pre; if (L==R) return rt; son[rt][0]=build(rt,L,mid-1); son[rt][1]=build(rt,mid+1,R); pushup(rt); return rt; } int findkth(int x,int k){ pushdown(x); if (size[son[x][0]]+1==k) return x; if (k<=size[son[x][0]]) return findkth(son[x][0],k); else return findkth(son[x][1],k-size[son[x][0]]-1); } void erase(int x){ if (!x) return; st[++top]=x; erase(son[x][0]); erase(son[x][1]); } int main(){ n=read(),m=read(); for (int i=1;i<=n;i++) a[i+1]=read(); Lmax[0]=Rmax[0]=Max[0]=val[0]=-Inf; a[1]=a[n+2]=-Inf; root=build(0,1,n+2); for (int i=1;i<=m;i++){ char op[10]; scanf("%s",op); if (op[2]==\'X\'){ printf("%d\\n",Max[root]); continue; } int pos=read()+1,tot=read(); if (op[0]==\'I\'){ int x=findkth(root,pos),y=findkth(root,pos+1); splay(x,0); splay(y,x); pushdown(x); pushdown(y); int z=son[y][0]; for (int i=1;i<=tot;i++) a[i]=read(); son[y][0]=build(y,1,tot); pushup(y),pushup(x); continue; } int x=findkth(root,pos-1),y=findkth(root,pos+tot); splay(x,0); splay(y,x); int z=son[y][0]; if (op[0]==\'D\') son[y][0]=fa[z]=0,erase(z); if (op[0]==\'M\') pushson(z,0,read()); if (op[0]==\'R\') pushson(z,1,-Inf); if (op[0]==\'G\') printf("%d\\n",sum[z]); pushup(y),pushup(x); } return 0; }
以上是关于BZOJ1500 [NOI2005]维修数列 splay的主要内容,如果未能解决你的问题,请参考以下文章