1 条题解

  • 0
    @ 2025-8-24 21:34:30

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 斯德哥尔摩
    **

    搬运于2025-08-24 21:34:30,当前版本为作者最后更新于2017-12-31 12:19:41,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    一看就知道是 LCT 裸题,直接上模板。。。

    这年头,题解怎么都喜欢用数组,唯一的结构体题解还用了指针,郁闷ing。。。

    所以,我来一发 无指针结构体,自我感觉挺好。。。

    还有那啥,不要用 STL 的栈,会 RE/WA 的。。。

    附上代码(紧紧凑凑80+行):

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define MAXN 10010//数组大小
    #define MAX 999999999//极值
    using namespace std;
    int n,m;
    struct node{//有父无指针结构体
        int son[2];
        int f,flag;
    }a[MAXN];
    inline int read(){//读优
        int date=0,w=1;char c=0;
        while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
        while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
        return date*w;
    }
    inline int isroot(int rt){//是否是根
        return a[a[rt].f].son[0]!=rt&&a[a[rt].f].son[1]!=rt;
    }
    inline void pushdown(int rt){//标记下传
        if(!rt||!a[rt].flag)return;
        a[a[rt].son[0]].flag^=1;a[a[rt].son[1]].flag^=1;a[rt].flag^=1;
        swap(a[rt].son[0],a[rt].son[1]);//别忘了交换左右节点。。。
    }
    inline void turn(int rt){//旋转,改进版
        int x=a[rt].f,y=a[x].f,k=a[x].son[0]==rt?0:1;
        if(!isroot(x)){//就是这里,判断是否是根
            if(a[y].son[0]==x)a[y].son[0]=rt;
            else a[y].son[1]=rt;
        }
        a[rt].f=y;a[x].f=rt;a[a[rt].son[!k]].f=x;
        a[x].son[k]=a[rt].son[!k];a[rt].son[!k]=x;
    }
    void splay(int rt){//伸展,也是改进版,应为要适应LCT。。。
        int top=0,stack[MAXN];//果断手写栈
        stack[++top]=rt;//第一个一定是根
        for(int i=rt;!isroot(i);i=a[i].f)stack[++top]=a[i].f;
        while(top)pushdown(stack[top--]);//暴力修改
        while(!isroot(rt)){//这里就基本无大改了
            int x=a[rt].f,y=a[x].f;
            if(!isroot(x)){
                if((a[x].son[0]==rt)^(a[y].son[0]==x))turn(rt);
                else turn(x);
            }
            turn(rt);//注意,是最后才进行,当初我把这句放到里面,然后就 WA 了。。。
        }
    }
    void access(int rt){//将 x 与 x所在树的根 连一条链
        for(int i=0;rt;i=rt,rt=a[rt].f){//暴力修改,耗时贼多,没有之一。。。
            splay(rt);
            a[rt].son[1]=i;
        }
    }
    inline void makeroot(int rt){access(rt);splay(rt);a[rt].flag^=1;}//将 x 变为树根
    int find(int rt){//找树根
        access(rt);splay(rt);
        while(a[rt].son[0])rt=a[rt].son[0];//一直往左走
        return rt;
    }
    inline void split(int x,int y){makeroot(x);access(y);splay(y);}搞出 x与y的链
    inline void cut(int x,int y){//割 x与y的链
        split(x,y);
        a[y].son[0]=a[x].f=0;
    }
    inline void link(int x,int y){makeroot(x);a[x].f=y;}//连 x与y的链
    int main(){
        char ch[10];
        int x,y;
        n=read();m=read();
        while(m--){
            scanf("%s",ch);x=read();y=read();
            if(ch[0]=='C')link(x,y);
            if(ch[0]=='D')cut(x,y);//基本操作不再多说。。。
            if(ch[0]=='Q'){
                if(find(x)==find(y))printf("Yes\n");//判断联通
                else printf("No\n");
            }
        }
        return 0;//终于敲完了(累死我了。。。)
    }
    
    
    • 1

    信息

    ID
    1150
    时间
    1000ms
    内存
    125MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者