zoukankan      html  css  js  c++  java
  • 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
    ");
                    continue;
                }
                pos1=find_pos(pos);
                pos2=find_pos(pos+c+1);
                printf("%d
    ",Get_sum(pos1,pos2));
            }
            else{
                printf("%d
    ",tr[rt].maxn);
            }
        }
        return 0;
    }
  • 相关阅读:
    通用XML读写和配置(二)
    C++多态中的VPTR
    如何查看Linux操作系统的位数?
    另类获取ORACLE导入导出(imp/exp)数据的进度信息
    成熟是明亮而不刺眼的光辉
    C/C++预处理运算符
    系统设计与规划一点总结
    Linux 任务计划之crontab命令
    linux挂载磁盘阵列
    Linux下JDK的中文显示
  • 原文地址:https://www.cnblogs.com/lnxcj/p/9662671.html
Copyright © 2011-2022 走看看