题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1500
操作1:把要插入的数字先建成一颗树,然后splay相应位置,直接将树连上去
操作2,3,4,5:都是splay普通操作
操作6:像维护线段树一样,同时维护max,maxl,maxr就行了
注意点:
旋转时maxl和maxr也要交换
要使用内存池,当弹出一个节点时,将它的两个子树丢进内存池中
same的值可能为0,所以要设为inf
max不能为空,所以初始应设成-inf,而不是0,否则update时会出错
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #define lson i<<1 #define rson i<<1|1 using namespace std; const int N=5e5+5; const int inf=1e9; int head,tail,q[N*10],root; int a[N],b[N],f[N],ch[N][2],key[N],sz[N],same[N],rev[N],sum[N],maxl[N],maxr[N],maxx[N]; inline void Clear(int x) { f[x]=ch[x][0]=ch[x][1]=key[x]=sz[x]=rev[x]=sum[x]=maxl[x]=maxr[x]=0; same[x]=inf; maxx[x]=-inf; } inline int get(int x) { return ch[f[x]][1]==x; } inline void delp(int x) { q[++tail]=x; } int newp() { head++; if (ch[q[head]][0]) delp(ch[q[head]][0]); if (ch[q[head]][1]) delp(ch[q[head]][1]); Clear(q[head]); return q[head]; } void update(int x) { sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x]; maxl[x]=max(maxl[ch[x][0]],key[x]+sum[ch[x][0]]+maxl[ch[x][1]]); maxr[x]=max(maxr[ch[x][1]],key[x]+sum[ch[x][1]]+maxr[ch[x][0]]); maxx[x]=max(maxx[ch[x][0]],maxx[ch[x][1]]); maxx[x]=max(maxx[x],maxr[ch[x][0]]+key[x]+maxl[ch[x][1]]); } void pushdown(int x) { if (x==0) return; if (same[x]!=inf) { if (ch[x][0]) { int lch=ch[x][0]; key[lch]=same[x]; sum[lch]=sz[lch]*same[x]; if (same[x]>=0) maxx[lch]=maxl[lch]=maxr[lch]=sum[lch]; else { maxx[lch]=same[x]; maxl[lch]=maxr[lch]=0; } same[lch]=same[x]; } if (ch[x][1]) { int rch=ch[x][1]; key[rch]=same[x]; sum[rch]=sz[rch]*same[x]; if (same[x]>=0) maxx[rch]=maxl[rch]=maxr[rch]=sum[rch]; else { maxx[rch]=same[x]; maxl[rch]=maxr[rch]=0; } same[rch]=same[x]; } same[x]=inf; } if (rev[x]) { if (ch[x][0]) { int now=ch[x][0]; rev[now]^=1; swap(ch[now][0],ch[now][1]); swap(maxl[now],maxr[now]); } if (ch[x][1]) { int now=ch[x][1]; rev[now]^=1; swap(ch[now][0],ch[now][1]); swap(maxl[now],maxr[now]); } rev[x]=0; } } int build(int l,int r,int fa,int *val) { if (l>r) return 0; int mid=(l+r)>>1; int now=newp(); f[now]=fa;key[now]=val[mid];maxx[now]=val[mid]; int lch=build(l,mid-1,now,val); int rch=build(mid+1,r,now,val); ch[now][0]=lch;ch[now][1]=rch; update(now); return now; } void Rotate(int x) { pushdown(f[x]); pushdown(x); int fa=f[x],ff=f[fa],kind=get(x); ch[fa][kind]=ch[x][kind^1];f[ch[x][kind^1]]=fa; ch[x][kind^1]=fa;f[fa]=x; f[x]=ff; if (ff) ch[ff][ch[ff][1]==fa]=x; update(fa); update(x); } void splay(int x,int y) { for(int fa;(fa=f[x])!=y;Rotate(x)) if (f[fa]!=y) Rotate((get(fa)==get(x))?fa:x); if (y==0) root=x; } int Find(int x) { int now=root; while(1) { pushdown(now); if (ch[now][0]&&sz[ch[now][0]]>=x) now=ch[now][0]; else { x-=sz[ch[now][0]]; if (x==1) return now; x--; now=ch[now][1]; } } } void Treaval(int x) { if(x) { pushdown(x); Treaval(ch[x][0]); printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,key = %2d sum = %2d maxsum=%2d ",x,ch[x][0],ch[x][1],f[x],sz[x],key[x],sum[x],maxx[x]); Treaval(ch[x][1]); } } void debug() {printf("%d ",root);Treaval(root);} int main() { int n,m; scanf("%d%d",&n,&m); a[1]=-inf;a[n+2]=inf;maxx[0]=-inf; for(int i=1;i<=n;i++) scanf("%d",&a[i+1]); for(int i=1;i<=500000;i++) delp(i); root=build(1,n+2,0,a); char s[20]; int pos,tot,c; while(m--) { scanf("%s",s); switch(s[0]) { case 'I': { scanf("%d%d",&pos,&tot); for(int i=1;i<=tot;i++) scanf("%d",&b[i]); int now=build(1,tot,0,b); int aa=Find(pos+1); int bb=Find(pos+2); splay(aa,0); splay(bb,aa); ch[ch[root][1]][0]=now; f[now]=ch[root][1]; update(ch[root][1]); update(root); //debug(); break; } case 'D': { scanf("%d%d",&pos,&tot); int aa=Find(pos); int bb=Find(pos+tot+1); splay(aa,0); splay(bb,aa); delp(ch[ch[root][1]][0]); ch[ch[root][1]][0]=0; update(ch[root][1]); update(root); //debug(); break; } case 'M': if (s[2]=='K') { scanf("%d%d%d",&pos,&tot,&c); int aa=Find(pos); int bb=Find(pos+tot+1); splay(aa,0); splay(bb,aa); int now=ch[ch[root][1]][0]; same[now]=c; key[now]=c; sum[now]=c*sz[now]; if (c>=0) maxx[now]=maxl[now]=maxr[now]=sum[now]; else { maxx[now]=c; maxl[now]=maxr[now]=0; } update(ch[root][1]); update(root); //debug(); } else { int aa=Find(1); int bb=Find(sz[root]); splay(aa,0); splay(bb,aa); printf("%d ",maxx[ch[ch[root][1]][0]]); } break; case 'R': { scanf("%d%d",&pos,&tot); if (tot==1) break; int aa=Find(pos); int bb=Find(pos+tot+1); splay(aa,0); splay(bb,aa); int now=ch[ch[root][1]][0]; rev[now]^=1; swap(ch[now][0],ch[now][1]); swap(maxl[now],maxr[now]); break; } case 'G': { scanf("%d%d",&pos,&tot); int aa=Find(pos); int bb=Find(pos+tot+1); splay(aa,0); splay(bb,aa); //debug(); printf("%d ",sum[ch[ch[root][1]][0]]); break; } } } return 0; }