zoukankan      html  css  js  c++  java
  • bzoj 2049 [Sdoi2008]Cave 洞穴勘测

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2049

    第一道LCT!

    很久才明白为什么要reverse。因为makeroot的splay是在原树上做的,所以深度真的改变,而且恰好符合reverse。

    简洁的模板:https://blog.csdn.net/yxuanwkeith/article/details/50991326

    学习论文:https://wenku.baidu.com/view/75906f160b4e767f5acfcedb.html

    特别奇怪的是第37行为什么导致RE?

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=1e4+5;
    int n,m,pre[N],c[N][2],rev[N],stack[N],top;
    int rdn()
    {
        int ret=0,fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')(ret*=10)+=ch-'0',ch=getchar();
        return ret*fx;
    }
    bool isroot(int x)
    {
        return c[pre[x]][0]!=x&&c[pre[x]][1]!=x;
    }
    void reverse(int x)
    {
        if(rev[x]){
            rev[c[x][0]]^=1;rev[c[x][1]]^=1;
            swap(c[x][0],c[x][1]);
            rev[x]=0;
        }
    }
    void rotate(int x)
    {
        int y=pre[x],z=pre[y],d=(x==c[y][1]);
        if(!isroot(y))c[z][y==c[z][1]]=x;
        pre[x]=z;pre[y]=x;
        c[y][d]=c[x][!d];pre[c[x][!d]]=y;c[x][!d]=y;
    }
    void splay(int x)
    {
        stack[top=1]=x;    //含x 
        for(int t=x;!isroot(t);t=pre[t])stack[++top]=pre[t];    //含根 
    //    for(int i=1;i<=top;i++)reverse(stack[i]);    //为什么这行会导致RE? 
        for(;top;top--)reverse(stack[top]);//
        for(;!isroot(x);rotate(x))
        {
            int y=pre[x],z=pre[y];
            if(isroot(y))continue;
            ((c[z][0]==y)^(c[y][0]==x))?rotate(x):rotate(y);
        }
    }
    void access(int x)
    {
        for(int t=0;x;c[x][1]=t,t=x,x=pre[x])splay(x);    //条件是x,不是isroot(x),因为是在原树上弄 
    }
    void makeroot(int x)
    {
        access(x);splay(x);rev[x]^=1;//rev,因为是在原树上splay,故深度改变。正好符合reverse 
    }
    void link(int x,int y)
    {
        makeroot(x);pre[x]=y;
    }
    void cut(int x,int y)
    {
        makeroot(x);access(y);splay(y);
        c[y][0]=0;pre[x]=0;
    }
    int find(int x)    //找所在原树的根 
    {
        access(x);splay(x);int t;
        for(t=x;c[t][0];t=c[t][0]);
        return t;
    }
    int main()
    {
        char ch[10];int x,y;
        n=rdn();m=rdn();
        for(int i=1;i<=m;i++)
        {
            scanf("%s",ch);x=rdn();y=rdn();
            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
    ");
                else printf("No
    ");
        }
        return 0;
    }
  • 相关阅读:
    点分治。。。。。
    巧克力
    离散化初步
    [NOI1998]:围巾裁剪
    关于Tarjan(3)——离线LCA
    Eigen学习笔记2-Matrix类
    Eigen学习
    Git使用入门笔记
    LeetCode 之二叉树中序遍历(使用栈实现)
    leetCode之二叉树数中序遍历(递归实现)
  • 原文地址:https://www.cnblogs.com/Narh/p/9232653.html
Copyright © 2011-2022 走看看