bzoj1500 维修数列(splay)
小破树splay的终极模板(gou)题,小细节很多
而我tm把容易错的地方基本都错了一遍。。。
随便列出几个我错的细节(太多了列不完都)。。。
1.不能找前驱和后继,因为不把标记推完就贸然splay会使标记传乱!
2.Make_same的标记不能记录修改的值,因为如果把某一区间修改成0标记无法下传!
3.下传Reverse标记时不但要转左右儿子,还要转左右最大值!
4.如果Max_sum<0,不能输出0!
5.在造标记时要把该点信息全部修改正确,因为他要更新上面的节点!
贴代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,cnt,tot,rt,tp,top; int kx[4000005]; int num[4000005]; char ac[105]; struct Tree{ int son[2]; bool mark,tag; int siz,fa; int val,sum; int lm,rm,maxn; }tr[500005]; void update(int o,int v){ tr[o].lm=max(tr[o].siz*v,0); tr[o].rm=max(tr[o].siz*v,0); tr[o].maxn=max(tr[o].siz*v,v); tr[o].val=v;tr[o].tag=1; tr[o].sum=tr[o].siz*v; } void pushdown(int o){ if(tr[o].tag){ if(tr[o].son[0])update(tr[o].son[0],tr[o].val); if(tr[o].son[1])update(tr[o].son[1],tr[o].val); tr[o].tag=tr[o].mark=0; } if(tr[o].mark){ tr[tr[o].son[0]].mark^=1; tr[tr[o].son[1]].mark^=1; swap(tr[tr[o].son[0]].lm,tr[tr[o].son[0]].rm); swap(tr[tr[o].son[1]].lm,tr[tr[o].son[1]].rm); swap(tr[tr[o].son[0]].son[0],tr[tr[o].son[0]].son[1]); swap(tr[tr[o].son[1]].son[0],tr[tr[o].son[1]].son[1]); tr[o].mark=0; } } void pushup(int o){ tr[o].sum=tr[tr[o].son[0]].sum+tr[tr[o].son[1]].sum+tr[o].val; tr[o].siz=tr[tr[o].son[0]].siz+tr[tr[o].son[1]].siz+1; tr[o].maxn=max(tr[tr[o].son[0]].maxn,tr[tr[o].son[1]].maxn); tr[o].maxn=max(tr[o].maxn,tr[tr[o].son[0]].rm+tr[tr[o].son[1]].lm+tr[o].val); tr[o].lm=max(tr[tr[o].son[0]].sum+tr[o].val+tr[tr[o].son[1]].lm,tr[tr[o].son[0]].lm); tr[o].rm=max(tr[tr[o].son[1]].sum+tr[o].val+tr[tr[o].son[0]].rm,tr[tr[o].son[1]].rm); } void rotate(int x){ int y=tr[x].fa,z=tr[y].fa; int typ=(x==tr[y].son[1]); tr[y].son[typ]=tr[x].son[typ^1]; tr[tr[x].son[typ^1]].fa=y; tr[x].son[typ^1]=y,tr[y].fa=x; tr[x].fa=z; if(z){ if(tr[z].son[1]==y)tr[z].son[1]=x; else tr[z].son[0]=x; } pushup(y);pushup(x); } void splay(int x,int goal){ for(int y;(y=tr[x].fa)!=goal;rotate(x)){ if(tr[y].fa!=goal){ rotate((x==tr[y].son[0])==(y==tr[tr[y].fa].son[0])?y:x); } } if(!goal)rt=x; } void build(int &u,int l,int r,int fa){ if(l>r)return; int mid=(l+r)>>1; if(top)u=kx[top--]; else u=++tot; tr[u].siz=1; tr[u].val=num[mid]; tr[u].fa=fa; build(tr[u].son[0],l,mid-1,u); build(tr[u].son[1],mid+1,r,u); pushup(u); } int find_pos(int x){ int u=rt; while(true){ pushdown(u); if(tr[tr[u].son[0]].siz+1==x)return u; else if(tr[tr[u].son[0]].siz>=x)u=tr[u].son[0]; else x-=tr[tr[u].son[0]].siz+1,u=tr[u].son[1]; } } void dfs(int u){ if(!u)return; tr[u].fa=0; dfs(tr[u].son[0]); dfs(tr[u].son[1]); tr[u].son[0]=tr[u].son[1]=0; tr[u].sum=tr[u].val=tr[u].siz=tr[u].tag=tr[u].mark=tr[u].lm=tr[u].rm=tr[u].maxn=0; kx[++top]=u; } void insert(int x,int u,int l,int r){ splay(x,0); splay(u,x); build(tr[u].son[0],l,r,u); pushup(u);pushup(x); } void Delete(int x,int y){ splay(x,0); splay(y,x); dfs(tr[y].son[0]); tr[y].son[0]=0; pushup(y);pushup(x); } void Make_same(int x,int y,int v){ splay(x,0); splay(y,x); if(!tr[y].son[0])return; tr[tr[y].son[0]].val=v;tr[tr[y].son[0]].tag=1; tr[tr[y].son[0]].lm=max(tr[tr[y].son[0]].siz*v,0); tr[tr[y].son[0]].rm=max(tr[tr[y].son[0]].siz*v,0); tr[tr[y].son[0]].maxn=max(tr[tr[y].son[0]].siz*v,v); tr[tr[y].son[0]].sum=tr[tr[y].son[0]].siz*v; pushup(y);pushup(x); } void Reverse(int x,int y){ splay(x,0); splay(y,x); if(!tr[y].son[0])return; if(!tr[tr[y].son[0]].tag){ tr[tr[y].son[0]].mark^=1; swap(tr[tr[y].son[0]].son[0],tr[tr[y].son[0]].son[1]); swap(tr[tr[y].son[0]].lm,tr[tr[y].son[0]].rm); } pushup(y);pushup(x); } int Get_sum(int x,int y){ splay(x,0); splay(y,x); return tr[tr[y].son[0]].sum; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&num[++cnt]); } num[0]=num[cnt+1]=tr[0].val=tr[0].maxn=-0x3f3f3f3f; build(rt,0,cnt+1,0); for(int i=1;i<=m;i++){ scanf("%s",ac+1); if(ac[1]=='I'){ int pos,pos1,pos2,c; scanf("%d%d",&pos,&c); for(int j=1;j<=c;j++){ scanf("%d",&num[++cnt]); } pos1=find_pos(pos+1); pos2=find_pos(pos+2); insert(pos1,pos2,cnt-c+1,cnt); } else if(ac[1]=='D'){ int pos,c,pos1,pos2; scanf("%d%d",&pos,&c); pos1=find_pos(pos); pos2=find_pos(pos+c+1); Delete(pos1,pos2); } else if(ac[1]=='M'&&ac[3]=='K'){ int pos,c,pos1,pos2,v; scanf("%d%d%d",&pos,&c,&v); pos1=find_pos(pos); pos2=find_pos(pos+c+1); Make_same(pos1,pos2,v); } else if(ac[1]=='R'){ int pos,c,pos1,pos2; scanf("%d%d",&pos,&c); pos1=find_pos(pos); pos2=find_pos(pos+c+1); Reverse(pos1,pos2); } else if(ac[1]=='G'){ int pos,c,pos1,pos2; scanf("%d%d",&pos,&c); if(c==0){ printf("0\n"); continue; } pos1=find_pos(pos); pos2=find_pos(pos+c+1); printf("%d\n",Get_sum(pos1,pos2)); } else{ printf("%d\n",tr[rt].maxn); } } return 0; }