zoukankan      html  css  js  c++  java
  • LCT(Link-Cut Tree)

    Link-cut tree(LCT)【可以理解为树链剖分+splay】

    给出如下定义:

      access(x):访问x节点

      perferred child:若以x为根的子树中最后被访问的节点在以x的儿子y为根的子树中,则称y为节点x的preferred child

      preferred edge:节点x与其preferred child之间的边

      preferred path:由preferred edge组成的路径

    每条preferred path用splay维护,记录splay的根接到上条重链的哪个节点

    操作

      每次访问一个点时,该点一直到根的路径上的点全部被修改,与preferred child断开并连到新的preferred child上,并打上翻转标记,也就是拆分(cut)和合并(link)两个操作,其余链上的维护可以通过下传标记(pushdown)解决

    例题:

      bzoj2002弹飞绵羊

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int Mx=200010; 
    int n,m,fa[Mx],l[Mx],r[Mx],root[Mx],siz[Mx],rev[Mx];
    void pushup(int x) { siz[x]=siz[l[x]]+siz[r[x]]+1; }
    void pushdown(int x) { if(rev[x]) rev[x]^=1,rev[l[x]]^=1,rev[r[x]]^=1,swap(l[x],r[x]); }
    void rotate(int x)
    {
        int y=fa[x];
        if(l[y]==x) l[y]=r[x],fa[r[x]]=y,r[x]=y,fa[x]=fa[y],fa[y]=x;
        else r[y]=l[x],fa[l[x]]=y,l[x]=y,fa[x]=fa[y],fa[y]=x;
        if(root[y]) root[y]=0,root[x]=1;
        else
            if(r[fa[x]]==y) r[fa[x]]=x;
            else l[fa[x]]=x;
        pushup(y);
    }
    void splay(int x)
    {
        while(!root[x])
        {
            int y=fa[x],yy=fa[y];
            if(root[y]) rotate(x);
            else
                if((l[yy]==y&&l[y]!=x)||(l[yy]!=y&&l[y]==x)) rotate(y),rotate(x);
                else rotate(x),rotate(x);
        }
        pushup(x);
    }
    void access(int x)
    {
        int y=0;
        while(x)
        {
            splay(x); root[r[x]]=1,root[y]=0;
            pushup(x); r[x]=y,y=x,x=fa[x];
        }
    }
    void rever(int x) { access(x); splay(x); rev[x]^=1; }
    void link(int x,int y) { rever(x); fa[l[x]]=0,root[l[x]]=1,l[x]=0,fa[x]=y; pushup(x); }
    void cut(int x,int y) { rever(x); access(y); splay(y); l[y]=0,fa[x]=0; }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) root[i]=1,siz[i]=1;
        for(int i=1;i<=n;i++)
        {
            int x; scanf("%d",&x);
            if(i+x<=n) link(i,i+x);
        }
        scanf("%d",&m);
        while(m--)
        {
            int num,x,k; scanf("%d",&num);
            if(num==1)
            {
                scanf("%d",&x); x++; 
                rever(x);
                printf("%d
    ",siz[l[x]]+1);
            }
            else
            {
                scanf("%d%d",&x,&k); x++;
                if(x+k>n) link(x,0);
                else link(x,x+k);
            }
        } 
    }

      bzoj2631 tree

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int Mx=200010;
    const int p=51061;
    int n,top,q[Mx],fa[Mx],son[Mx][2],siz[Mx],rev[Mx];
    unsigned int val[Mx],sum[Mx],add_tag[Mx],mul_tag[Mx];
    inline int read()
    {
        int x=0,f=1;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 cal(int x,int a,int b)
    {
        if(!x) return ;
        val[x]=(a*val[x]+b)%p;
        sum[x]=(a*sum[x]+b*siz[x])%p;
        add_tag[x]=(a*add_tag[x]+b)%p;
        mul_tag[x]=(a*mul_tag[x])%p;
    }
    int isroot(int x)
    {
        if(son[fa[x]][0]!=x&&son[fa[x]][1]!=x) return 1;
        return 0;
    }
    void pushup(int x)
    {
        int l=son[x][0],r=son[x][1];
        sum[x]=(sum[l]+sum[r]+val[x])%p;
        siz[x]=(siz[l]+siz[r]+1)%p;
    }
    void pushdown(int x)
    {
        int l=son[x][0],r=son[x][1];
        if(rev[x])
            rev[x]^=1,rev[l]^=1,rev[r]^=1,
            swap(son[x][0],son[x][1]);
        int a=add_tag[x],m=mul_tag[x];
        add_tag[x]=0,mul_tag[x]=1;
        if(a!=0||m!=1) cal(l,m,a),cal(r,m,a);
    }
    void rotate(int x)
    {
        int l=0,r=0,y=fa[x],yy=fa[y];
        if(son[y][1]==x) l=1; r=l^1;
        if(!isroot(y)) son[yy][(son[yy][1]==y)]=x;
        fa[x]=yy,fa[y]=x,fa[son[x][r]]=y,son[y][l]=son[x][r],son[x][r]=y;
        pushup(y);pushup(x);
    }
    void splay(int x)
    {
        q[++top]=x;
        for(int i=x;!isroot(i);i=fa[i]) q[++top]=fa[i];
        while(top) pushdown(q[top--]);
        while(!isroot(x))
        {
            int y=fa[x],yy=fa[y];
            if(!isroot(y))
            {
                if((son[y][0]==x)^(son[yy][0]==y)) rotate(x);
                else rotate(y);
            }
            rotate(x);
        }
    }
    void access(int x)
    {
        for(int t=0;x;t=x,x=fa[x])
            splay(x),son[x][1]=t,pushup(x);
    }
    void rever(int x)
    {
        access(x); splay(x); rev[x]^=1;
    }
    void link(int x,int y)
    {
        rever(x); fa[x]=y;
    }
    void split(int x,int y)
    {
        rever(y); access(x); splay(x);
    }
    void cut(int x,int y)
    {
        rever(x); access(y); splay(y);
        son[y][0]=fa[x]=0;
    }
    signed main()
    {
        int m; scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) val[i]=sum[i]=mul_tag[i]=siz[i]=1;
        for(int i=1,x,y;i<n;i++) scanf("%d%d",&x,&y),link(x,y);
        while(m--)
        {
            char ch[10]; scanf("%s",ch); int x,y,c; x=read(),y=read();
            if(ch[0]=='+') c=read(),split(x,y),cal(x,1,c);
            if(ch[0]=='-') cut(x,y),x=read(),y=read(),link(x,y);
            if(ch[0]=='*') c=read(),split(x,y),cal(x,c,0);
            if(ch[0]=='/') split(x,y),printf("%d
    ",sum[x]);
        }
        return 0;
    }
  • 相关阅读:
    学习笔记
    django中嵌入百度editor插件
    定位屡试不爽
    django忘记管理员账号和密码处理
    linux上配置java环境
    python3学习问题汇总
    Android系统框架
    python深复制和浅复制
    装饰器原理和装饰器参数使用
    小白神器
  • 原文地址:https://www.cnblogs.com/xiaoxubi/p/6422151.html
Copyright © 2011-2022 走看看