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\n");
            else printf("No\n");
    }
    return 0;
}

 

posted on 2018-06-27 10:28  Narh  阅读(160)  评论(0编辑  收藏  举报

导航