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;
}

 

转载于:https://www.cnblogs.com/lnxcj/p/9662671.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值