• 【题解】Luogu SP8791 DYNALCA


    原题传送门

    这道题的难点就在如何求LCA:

    我们珂以先对其中一个点进行access操作,然后对另一个点进行access操作,因为LCA到根的边一定都由第一次access变为实边了,在之后的这一次access操作的最后一条从虚边变为实边的边的父亲就是两点的LCA

    回求LCA后,剩下的几乎是模板,但有两种做法

    1.建立虚拟点n+1,保证一直是一颗有n+1个点的树,写起来比较无脑(lct部分珂以复制),常数比较大

    #include <bits/stdc++.h>
    #define N 100005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf; 
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline void Swap(register int &a,register int &b)
    {
        a^=b^=a^=b;
    }
    struct Link_Cut_Tree{
        int c[N][2],fa[N],top,q[N],rev[N];
        inline void pushdown(register int x)
        {
            if(rev[x])
            {
                register int l=c[x][0],r=c[x][1];
                rev[l]^=1,rev[r]^=1,rev[x]^=1;
                Swap(c[x][0],c[x][1]);
            }
        }
        inline bool isroot(register int x)
        {
            return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
        }
        inline void rotate(register int x)
        {
            int y=fa[x],z=fa[y],l,r;
            l=c[y][0]==x?0:1;
            r=l^1;
            if(!isroot(y))
                c[z][c[z][0]==y?0:1]=x;
            fa[x]=z;
            fa[y]=x;
            fa[c[x][r]]=y;
            c[y][l]=c[x][r];
            c[x][r]=y;
        }
        inline void splay(register int x)
        {
            top=1;
            q[top]=x;
            for(register int i=x;!isroot(i);i=fa[i])
                q[++top]=fa[i];
            for(register int i=top;i;--i)
                pushdown(q[i]);
            while(!isroot(x))
            {
                int y=fa[x],z=fa[y];
                if(!isroot(y))
                    rotate((c[y][0]==x)^(c[z][0]==y)?(x):(y));
                rotate(x);
            }
        }
        inline void access(register int x)
        {
            for(register int t=0;x;t=x,x=fa[x])
            {
                splay(x);
                c[x][1]=t;
            }
        }
        inline void makeroot(register int x)
        {
            access(x);
            splay(x);
            rev[x]^=1;
        }
        inline void split(register int x,register int y)
        {
            makeroot(x);
            access(y);
            splay(y);
        }
        inline void cut(register int x,register int y)
        {
            split(x,y);
            c[y][0]=0;
            fa[x]=0;
        }
        inline void link(register int x,register int y)
        {
            makeroot(x);
            fa[x]=y;	
        }
        inline int LCA(register int x,register int y)
        {
            access(x);
            int t;
            for(t=0;y;t=y,y=fa[y])
            {
                splay(y);
                c[y][1]=t;	
            }	
            return t;
        }	
    }T;
    int fa[N];
    int main()
    {
        int n=read(),m=read();
        for(register int i=1;i<=n;++i)
            T.link(i,n+1),fa[i]=n+1;
        while(m--)
        {
            char c=getchar();
            while(c!='k'&&c!='t'&&c!='a')
                c=getchar();
            if(c=='k')
            {
                int x=read(),y=read();
                T.cut(x,fa[x]);
                fa[x]=y;
                T.link(x,y);
            }
            else if(c=='t')
            {
                int x=read();
                T.cut(x,fa[x]);
                fa[x]=n+1;
                T.link(x,n+1);
            }
            else
            {
                int x=read(),y=read();
                T.makeroot(n+1);
                write(T.LCA(x,y)),puts("");
            }
        }
        return 0;
     } 
    

    2.按照题目加边,删边(常数小,容易写错)

    注意:cut和LCA操作是不能使用makeroot操作的,因为makeroot本身会修改树上的LCA关系,当然link操作使用makeroot是没有关系的

    #include <bits/stdc++.h>
    #define N 100005
    #define getchar nc
    using namespace std;
    inline char nc(){
        static char buf[100000],*p1=buf,*p2=buf; 
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
    }
    inline int read()
    {
        register int x=0,f=1;register char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*f;
    }
    inline void write(register int x)
    {
        if(!x)putchar('0');if(x<0)x=-x,putchar('-');
        static int sta[20];register int tot=0;
        while(x)sta[tot++]=x%10,x/=10;
        while(tot)putchar(sta[--tot]+48);
    }
    inline void Swap(register int &a,register int &b)
    {
        a^=b^=a^=b;
    }
    struct Link_Cut_Tree{
        int c[N][2],fa[N],top,q[N],rev[N];
        inline void pushdown(register int x)
        {
            if(rev[x])
            {
                register int l=c[x][0],r=c[x][1];
                rev[l]^=1,rev[r]^=1,rev[x]^=1;
                Swap(c[x][0],c[x][1]);
            }
        }
        inline bool isroot(register int x)
        {
            return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
        }
        inline void rotate(register int x)
        {
            int y=fa[x],z=fa[y],l,r;
            l=c[y][0]==x?0:1;
            r=l^1;
            if(!isroot(y))
                c[z][c[z][0]==y?0:1]=x;
            fa[x]=z;
            fa[y]=x;
            fa[c[x][r]]=y;
            c[y][l]=c[x][r];
            c[x][r]=y;
        }
        inline void splay(register int x)
        {
            top=1;
            q[top]=x;
            for(register int i=x;!isroot(i);i=fa[i])
                q[++top]=fa[i];
            for(register int i=top;i;--i)
                pushdown(q[i]);
            while(!isroot(x))
            {
                int y=fa[x],z=fa[y];
                if(!isroot(y))
                    rotate((c[y][0]==x)^(c[z][0]==y)?(x):(y));
                rotate(x);
            }
        }
        inline void access(register int x)
        {
            for(register int t=0;x;t=x,x=fa[x])
            {
                splay(x);
                c[x][1]=t;
            }
        }
        inline void makeroot(register int x)
        {
            access(x);
            splay(x);
            rev[x]^=1;
        }
        inline void cut(register int x)
        {
            access(x);
            splay(x);
            fa[c[x][0]]=0;
            c[x][0]=0;
        }
        inline void link(register int x,register int y)
        {
            makeroot(x);
            fa[x]=y;	
        }
        inline int LCA(register int x,register int y)
        {
            access(x);
            int t;
            for(t=0;y;t=y,y=fa[y])
            {
                splay(y);
                c[y][1]=t;	
            }	
            return t;
        }	
    }T;
    int fa[N];
    int main()
    {
        int n=read(),m=read();
        while(m--)
        {
            char c=getchar();
            while(c!='k'&&c!='t'&&c!='a')
                c=getchar();
            if(c=='k')
            {
                int x=read(),y=read();
                T.link(x,y);
            }
            else if(c=='t')
            {
                int x=read();
                T.cut(x);
            }
            else
            {
                int x=read(),y=read();
                write(T.LCA(x,y)),puts("");
            }
        }
        return 0;
     } 
    
  • 相关阅读:
    现实世界的Windows Azure:采访圣地亚哥公共安全小组的技术经理Adrian Gonzalez
    Casablanca发布:一个用C++访问云的本地类库
    现实世界的Windows Azure:采访IDV解决方案的副总经理Scott Caulk
    Rock Paper Azure Challenge春季比赛来了!
    上海职场六大关键词完全搜集之:才市
    理解 Delphi 的类(十一) 深入类中的方法[8] 抽象方法与抽象类
    理解 Delphi 的类(十一) 深入类中的方法[10] 构造方法与析构方法
    TScreen 类 获取字体列表
    理解 Delphi 的类(十一) 深入类中的方法[9] 不能被覆盖的方法与不能被继承的类
    理解 Delphi 的类(十一) 深入类中的方法[13] 方法的调用约定
  • 原文地址:https://www.cnblogs.com/yzhang-rp-inf/p/10204881.html
Copyright © 2020-2023  润新知