• SPLAY,LCT学习笔记(五)


    这一篇重点探讨LCT的应用

    例:bzoj 2631 tree2(国家集训队)

    LCT模板操作之一,利用SPLAY可以进行区间操作这一性质对维护懒惰标记,注意标记下传顺序和如何下传

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define uint unsigned int
    #define mode 51061
    using namespace std;
    uint c[100005][2];
    uint v[100005];
    uint s[100005];
    uint alazy[100005];
    uint mlazy[100005];
    uint f[100005];
    uint ttag[100005];
    uint huge[100005];
    uint n,m;
    char ss[5];
    bool berot(uint rt)
    {
        if(c[f[rt]][0]==rt||c[f[rt]][1]==rt)
        {
            return 0;
        }
        return 1;
    }
    void reverse(uint rt)
    {
        swap(c[rt][0],c[rt][1]);
        ttag[rt]^=1;
    }
    void update(uint rt)
    {
        huge[rt]=huge[c[rt][0]]+huge[c[rt][1]]+1;
        s[rt]=(s[c[rt][0]]+s[c[rt][1]]+v[rt])%mode;
    }
    void mul(uint rt,uint val)
    {
        s[rt]*=val;
        s[rt]%=mode;
        v[rt]*=val;
        v[rt]%=mode;
        alazy[rt]*=val;
        alazy[rt]%=mode;
        mlazy[rt]*=val;
        mlazy[rt]%=mode;
    }
    void add(uint rt,uint val)
    {
        s[rt]+=val*huge[rt];
        s[rt]%=mode;
        alazy[rt]+=val;
        alazy[rt]%=mode;
        v[rt]+=val;
        v[rt]%=mode;
    }
    void pushdown(uint rt)
    {
        if(mlazy[rt]!=1)
        {
            mul(c[rt][0],mlazy[rt]);
            mul(c[rt][1],mlazy[rt]);
            mlazy[rt]=1;
        }
        if(alazy[rt])
        {
            add(c[rt][0],alazy[rt]);
            add(c[rt][1],alazy[rt]);
            alazy[rt]=0;
        }
        if(ttag[rt])
        {
            if(c[rt][0])
            {
                reverse(c[rt][0]);
            }
            if(c[rt][1])
            {
                reverse(c[rt][1]);
            }
            ttag[rt]=0;
        }
    }
    void repush(uint rt)
    {
        if(!berot(rt))
        {
            repush(f[rt]);
        }
        pushdown(rt);
    }
    void rotate(uint rt)
    {
        uint ltyp=0;
        uint fa=f[rt];
        uint ffa=f[fa];
        if(c[fa][1]==rt)
        {
            ltyp=1;
        }
        if(!berot(fa))
        {
            if(c[ffa][0]==fa)
            {
                c[ffa][0]=rt;
            }else
            {
                c[ffa][1]=rt;
            }
        }
        c[fa][ltyp]=c[rt][ltyp^1];
        c[rt][ltyp^1]=fa;
        f[c[fa][ltyp]]=fa;
        f[fa]=rt;
        f[rt]=ffa;
        update(fa);
    }
    void splay(uint rt)
    {
        repush(rt);
        while(!berot(rt))
        {
            uint fa=f[rt];
            uint ffa=f[fa];
            if(!berot(fa))
            {
                if((c[fa][0]==rt&&c[ffa][0]!=fa)||(c[fa][1]==rt&&c[ffa][1]!=fa))
                {
                    rotate(rt);
                }else
                {
                    rotate(fa);
                }
            }
            rotate(rt);
        }
        update(rt);
    }
    void access(uint rt)
    {
        uint y=0;
        while(rt)
        {
            splay(rt);
            c[rt][1]=y;
            update(rt);
            y=rt;
            rt=f[rt];
        }
    }
    void makeroot(uint rt)
    {
        access(rt);
        splay(rt);
        reverse(rt);
    }
    void split(uint st,uint ed)
    {
        makeroot(st);
        access(ed);
        splay(ed);
    }
    void link(uint st,uint ed)
    {
        makeroot(st);
        f[st]=ed;
    }
    void cut(uint st,uint ed)
    {
        split(st,ed);
        f[st]=c[ed][0]=0;
    }
    inline uint read()
    {
        uint f=1,x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f =1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int main()
    {
        n=read(),m=read();
        for(uint i=1;i<=n;i++)
        {
            huge[i]=1;
            v[i]=1;
            mlazy[i]=1;
        }
        for(uint i=1;i<n;i++)
        {
            uint x=read(),y=read();
            link(x,y);
        }
        while(m--)
        {
            scanf("%s",ss);
            if(ss[0]=='+')
            {
                uint x=read(),y=read(),z=read();
                split(x,y);
                add(y,z);
            }else if(ss[0]=='-')
            {
                uint x=read(),y=read(),z=read(),q=read();
                cut(x,y);
                link(z,q);
            }else if(ss[0]=='*')
            {
                uint x=read(),y=read(),z=read();
                split(x,y);
                mul(y,z);
            }else
            {
                uint x=read(),y=read();
                split(x,y);
                printf("%u
    ",s[y]);			
            }
        }
        return 0;
    }

    例:bzoj 3282 luogu 3690 link-cut-tree 模板

    模板题,用SPLAY维护即可

    注意判断加边的合法性

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    int c[400005][2];
    ll s[400005];
    int f[400005];
    bool ttag[400005];
    int v[400005];
    int n,m;
    bool berot(int rt)
    {
        if(c[f[rt]][0]==rt||c[f[rt]][1]==rt)
        {
            return 0;
        }
        return 1;
    }
    inline int read()
    {
        int f=1,x=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    void update(int rt)
    {
        s[rt]=(ll)s[c[rt][0]]^(ll)s[c[rt][1]]^(ll)v[rt];
    }
    void reverse(int rt)
    {
        swap(c[rt][0],c[rt][1]);
        ttag[rt]^=1;
    }
    void pushdown(int rt)
    {
        if(ttag[rt])
        {
            if(c[rt][0])reverse(c[rt][0]);
            if(c[rt][1])reverse(c[rt][1]);
            ttag[rt]=0;
        }
    }
    void repush(int rt)
    {
        if(!berot(rt))
        {
            repush(f[rt]);
        }
        pushdown(rt);
    }
    void rotate(int rt)
    {
        int ltyp=0;
        int fa=f[rt];
        int ffa=f[fa];
        if(c[fa][1]==rt)
        {
            ltyp=1;
        }
        if(!berot(fa))
        {
            if(c[ffa][1]==fa)
            {
                c[ffa][1]=rt;
            }else
            {
                c[ffa][0]=rt;
            }
        }
        c[fa][ltyp]=c[rt][ltyp^1];
        c[rt][ltyp^1]=fa;
        f[c[fa][ltyp]]=fa;
        f[fa]=rt;
        f[rt]=ffa;
        update(fa);
    }
    void splay(int rt)
    {
        repush(rt);
        while(!berot(rt))
        {
            int fa=f[rt];
            int ffa=f[fa];
            if(!berot(fa))
            {
                if((c[fa][0]==rt&&c[ffa][0]!=fa)||(c[fa][1]==rt&&c[ffa][1]!=fa))
                {
                    rotate(rt);
                }else
                {
                    rotate(fa);
                }
            }
            rotate(rt);
        }
        update(rt);
    }
    void access(int rt)
    {
        int y=0;
        while(rt)
        {
            splay(rt);
            c[rt][1]=y;
            update(rt);
            y=rt;
            rt=f[rt];
        }
    }
    void makeroot(int rt)
    {
        access(rt);
        splay(rt);
        reverse(rt);
    }
    int getroot(int rt)
    {
        access(rt);
        splay(rt);
        while(c[rt][0])
        {
            pushdown(rt);
            rt=c[rt][0];
        }
        return rt;
    }
    void link(int st,int ed)
    {
        makeroot(st);
        if(getroot(ed)==st)
        {
            return;
        }
        f[st]=ed;
    }
    void cut(int st,int ed)
    {
        makeroot(ed);
        if(getroot(st)==ed&&f[ed]==st&&!c[ed][1])
        {
            c[st][0]=f[ed]=0;
            update(st);
        }
    }
    void split(int st,int ed)
    {
        makeroot(st);
        access(ed);
        splay(ed);
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
        {
            v[i]=read();
        }
        while(m--)
        {
            int typ=read(),x=read(),y=read();
            if(typ==0)
            {
                split(x,y);
                printf("%lld
    ",s[y]);
            }else if(typ==1)
            {
                link(x,y);
            }else if(typ==2)
            {
                cut(x,y);
            }else
            {
                splay(x);
                v[x]=y;
            }
        }
        return 0;
    }

    在上面两个模板应用中,有一个要点:repush!

    在传递翻转标记时,我们要注意一定从上向下传标记!

  • 相关阅读:
    super关键字
    aspcms 留言 搜索
    aspcms标签
    随机添加一个Class,Class提前写好
    python实现进度条
    linux 下获取文件名的md5值
    linux下 批量压缩与批量解压
    linux下批量新建/删除 文件或目录
    python——pip导出导入安装包
    python Scrapy爬虫框架
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10764212.html
Copyright © 2020-2023  润新知