BZOJ_1500_[NOI2005]维修数列_splay
BZOJ_1500_[NOI2005]维修数列_splay
题意:
分析:
节点维护从左开始的最大连续子段和,从右开始的最大连续子段和,区间的最大连续子段和
插入:重新建一棵树,把pos旋到根,把pos+1旋到根的右儿子,直接插到根的右儿子的左儿子上
删除:节点回收,用循环队列或者栈存一下删除的节点,新建的时候用。
修改和翻转正常做,这两个标记互不影响。记得翻转时左右儿子的信息都要交换。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 1000050 #define ls ch[p][0] #define rs ch[p][1] #define get(x) (x==ch[f[x]][1]) int ch[N][2],f[N],siz[N],val[N],n,m; int cov[N],turn[N],maxl[N],maxr[N],maxm[N]; int S[N],top,sum[N],rt,a[N],sz,tot; int other_root; char opt[20]; void clear(int x){if(!x)return ;ch[x][0]=ch[x][1]=f[x]=val[x]=siz[x]=sum[x]=turn[x]=maxl[x]=maxr[x]=maxm[x]=0;cov[x]=0x3f3f3f3f;} void print(int p) { if(!p)return ; if(ls)print(ls); printf("p=%d val[p]=%d\n",p,val[p]); if(rs)print(rs); } int newnode(int v) { int p; if(top)p=S[--top]; else p=++tot; clear(p); val[p]=v;siz[p]=1; maxl[p]=maxr[p]=v>0?v:0; maxm[p]=v; return p; } void update(int p) { if(!p)return ; siz[p]=siz[ls]+siz[rs]+1; sum[p]=sum[ls]+sum[rs]+val[p]; maxl[p]=max(maxl[ls],sum[ls]+val[p]+maxl[rs]); maxr[p]=max(maxr[rs],sum[rs]+val[p]+maxr[ls]); maxm[p]=val[p]; maxm[p]=max(max(maxm[p],maxm[ls]),maxm[rs]); maxm[p]=max(maxm[p],maxr[ls]+val[p]+maxl[rs]); } void pushdown(int p) { if(cov[p]!=0x3f3f3f3f) { int t=cov[p]; cov[p]=0x3f3f3f3f; cov[ls]=cov[rs]=t; val[ls]=val[rs]=t; sum[ls]=siz[ls]*t; sum[rs]=siz[rs]*t; maxl[ls]=maxr[ls]=t>0?sum[ls]:0; maxm[ls]=t>0?sum[ls]:t; maxl[rs]=maxr[rs]=t>0?sum[rs]:0; maxm[rs]=t>0?sum[rs]:t; } if(turn[p]) { swap(ls,rs); swap(maxl[ls],maxr[ls]); swap(maxl[rs],maxr[rs]); turn[ls]^=1; turn[rs]^=1; turn[p]=0; } } void rotate(int x) { int y=f[x],z=f[y],k=get(x); ch[y][k]=ch[x][k^1];f[ch[y][k]]=y; ch[x][k^1]=y;f[y]=x;f[x]=z; if(z) ch[z][ch[z][1]==y]=x; update(y),update(x); if(rt==y)rt=x; } void splay(int x,int y) { for(int fa;(fa=f[x])!=y;rotate(x)) if(f[fa]!=y) rotate((get(x)==get(fa)) ? fa : x); } int find(int x) { int p=rt; while(1) { pushdown(p); if(x<=siz[ls])p=ls; else { x-=siz[ls]+1; if(!x) return p; p=rs; } } } void print1() { for(int i=1;i<=sz;i++){int p=find(i);printf("p=%d val[p]=%d\n",p,val[p]);} } void build(int fa,int l,int r) { if(l>r)return ; int mid=l+r>>1; ch[fa][mid>fa]=mid; f[mid]=fa; val[mid]=a[mid-1]; siz[mid]=1; build(mid,l,mid-1); build(mid,mid+1,r); update(mid); } void build_merge(int fa,int l,int r,int flg) { if(l>r)return ; int mid=l+r>>1; int p=newnode(a[mid]); val[p]=a[mid]; ch[fa][flg]=p; f[p]=fa; build_merge(p,l,mid-1,0); build_merge(p,mid+1,r,1); update(p); } void insert(int x,int cnt) { int i; for(i=1;i<=cnt;i++) scanf("%d",&a[i]); sz+=cnt; int p=x+1; x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); build_merge(p,1,cnt,0); } void rec(int p) { if(!p)return ; if(ls)rec(ls); ls=0; if(rs)rec(rs); rs=0; clear(p); S[top++]=p; } void del(int x,int p) { x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); sz-=siz[ls]; rec(ls); ls=0; update(p);update(x); } void modify(int x,int p,int c) { x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); cov[ls]=c; val[ls]=c; sum[ls]=c*siz[ls]; maxl[ls]=maxr[ls]=c>0?sum[ls]:0; maxm[ls]=c>0?sum[ls]:c; update(p);update(x); } void reverse(int x,int p) { x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); turn[ls]^=1; swap(maxl[ls],maxr[ls]); update(p);update(x); } void getsum(int x,int p) { x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); printf("%d\n",sum[ls]); } void getmax_sum() { int x=1,p=sz; x=find(x); p=find(p); splay(x,f[rt]); splay(p,rt); printf("%d\n",maxm[ls]); } int main() { scanf("%d%d",&n,&m); memset(cov,0x3f,sizeof(cov)); sz=n+2;tot=n+2; int i,x,y,z; for(i=1;i<=n;i++) scanf("%d",&a[i]); build(0,1,n+2); rt=n+3>>1; for(i=1;i<=m;i++) { scanf("%s",opt); if(opt[2]=='S'){ scanf("%d%d",&x,&y); insert(x+1,y); }else if(opt[2]=='L'){ scanf("%d%d",&x,&y); del(x,x+y+1); }else if(opt[2]=='K'){ scanf("%d%d%d",&x,&y,&z); modify(x,x+y+1,z); }else if(opt[2]=='V'){ scanf("%d%d",&x,&y); reverse(x,x+y+1); }else if(opt[2]=='T'){ scanf("%d%d",&x,&y); getsum(x,x+y+1); }else{ getmax_sum(); } } }