LCT问题

Update on 2017/4/17 
多坑慎入…… 
这篇文章不仅没有讲什么虚实边,作者还是个智障。 
大家如果要看的话建议先去参考其他人的TAT 
窝理解清楚再补。。。QAQ


这次不是在很多人的帮助下……而是自己调的代码、、、 
略微看了看自己LCT掉进去的几个坑、、、 
略微介绍一下: 
LCT的类似于树链剖分,只不过树链剖分是静态的,而LCT是动态的。 
LCT用Splay来维护每一条重链,而且在初始情况下,LCT是没有轻重链之分的。 
请注意,这里Splay维护的是按照深度递增的顺序来进行排序的。 
找到一张图是这样的: 
图侵删
把这个树变成LCT之后…… 
树变成LCT 
核心操作: 
Access(v): 
访问一个节点,其作用是把该点到LCT的根的路径都变成重链,由于我们维护LCT的时候是用的Splay,我们要把v这个节点Splay到根,也就是Splay到LCT的总根,这是一切操作的基础。 
Splay操作: 
把一个点伸展到它所在重链的根。 
请注意一件事情,也是我最初极为困惑的事情。 
在我们学习Splay的时候,我们的根节点的父亲是0,然而这里一条重链的根节点的父亲显然不是0,为了区分轻边重链,我们会使得根节点的父亲的左右儿子并不是根节点。 
这里我找了网上的一张图。 
aaa
这张图片里面,7的父亲是1,然而1是在浅红色重链里面的,即它是Splay的最左边节点(因为深度递增),所以它是没有左右儿子的,对吧?然而:7的父亲是1,这点却是一个不争的事实。 
也就是说,我们通过什么来判断这个点是否是维护这条重链的Splay的根呢? 
显然,我们只要看父亲节点的左右儿子里有没有它即可。 
FRT(find root寻找原来的树的根) 
请注意这里的root并不是LCT的根,而是原来那个树的根,切记切记。 
大概我们来想想就是这样: 
首先,根节点是深度最小的点。 
所以我们考虑Access(v),v这里是任意一个节点。 
然后Splay(v),走到它的最左端即可。 
MRT(make root换根操作) 
请注意,这里的换根操作也是原来的树的根。 
所以说我们只需要这样就行了。 
网上的图片…… 
换
我们把u换成v,也就意味着我们在保证其树的父子关系不变的情况下,使得v的深度最小。 
那么也就意味着,我们只需要先Access(v),Splay(v),然后打个翻转标记即可。 
这里要注意的一点是,如果询问跟固定一个根有关,在询问的时候一定要记住把根换回来…… 
Findroot可以找到当前原树的根,也就意味着我们把u换成v之后,Findroot的返回值就是v了。 
Cut操作: 
切断一条边。 
显然在Cut的时候不是简单的找到两个点然后一划就行了的。 
我们设Cut(u,v)。 
MRT(u),Access(v),Splay(v)。 
然后我们就会知道u一定在v的左儿子的位置,然后把v的左儿子标成0,u的父亲标成0即可。 
Link操作: 
连接一条边。 
在连接之前我们肯定要先断掉之前的边『否则你的树形结构就被破坏了』。 
我们考虑已经Cut完毕了,现在要连接(u,v),那么只需要: 
MRT(u),t[u].par = v即可。 
当然了……你随便把哪个当作父亲都是可以的。 
模板题是弹飞绵羊。 
问题在于…… 
询问的时候能处理什么? 
至少能处理一种东西: 
节点深度。 
Access(v),Splay(v),return t[lc].sz即可。 
BZOJ2002 
『题意』 
有一群弹簧(1~n),它们喜欢弹飞绵羊,每个弹簧可以让绵羊向后弹Ai格,如果绵羊被弹到超过n的范围,就算是被弹飞了,现在可以更改弹簧的后弹绵羊的能力,而有一个人会在某个弹簧上放一个绵羊,给出绵羊经过几次会被弹飞。 
分析: 
考虑我们虚拟一个节点标号为n+1,如果第i个弹簧能将绵羊弹飞到i + j,那么i - > min(i + j,n + 1)连边。 
更改弹簧能力也就意味着Link&&Cut操作,放羊操作相当于询问节点的深度。 
这题就这么过去了……第一次写的话调了好长时间。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define Repl(i,n) for(int i = 1,ls; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define RDD(i,x,n) for(int i = x; i >= n; i --)
#define u t[x]
#define debug puts("**")
#define debug2 puts("404 NOT FOUND")
#define lc ch[0]
#define rc ch[1]
#define tc ch[ty]
#define vc ch[!ty]
#define v edge[i].to
#define ulfc t[u.lc]
#define o t[y]
#define urtc t[u.rc]
#define p u.par
const int N = 200005;
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
int read(){
    char ch = getchar();
    while(ch < '0' || ch > '9')ch = getchar ();
    int x = 0;
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar ();
    return x;
}
int n,m;
struct LCT{
    int ch[2],par,sz;
    bool rev;
    LCT(){sz = 1,ch[0] = ch[1] = par = 0;}
    void Rev(){rev ^= 1;swap(lc,rc);}
}t[N];
int sgn(int x){return t[p].lc == x ? 0 : t[p].rc == x ? 1 : -1;}
void sc(int x,int y,bool ty){u.tc = y,o.par = x;}
void Upd(int x){if(x)u.sz = ulfc.sz + urtc.sz + 1;}
void Dw(int x){
    if(u.rev)
        ulfc.Rev(),urtc.Rev(),u.rev ^= 1;
}
void Fix(int x){if(~sgn(x))Fix(p);Dw(x);}
void Rot(int x,bool ty){
    int y = p;
    //printf("ROTING:%d %d %d %d\n",x,y,o.par,ty);
    if(~sgn(y))sc(o.par,x,sgn(y));
    else p = o.par;
    sc(y,u.vc,ty),sc(x,y,!ty),Upd(y);
}
int Splay(int x){

    Fix(x);
    int d0,d1,y;
    //printf("x : %d x的父亲%d\n",x,p);
    //debug2;
    while((~(d0 = sgn(x)))){
        if(~(d1 = sgn(y = p)))Rot(d0 ^ d1 ? x : y,d0),Rot(x,d1);
        else Rot(x,d0);
    }
    //Rep_0(i,n + 2)
    //  printf("~~~%d %d %d %d~~\n",i,t[i].par,t[i].ch[0],t[i].ch[1]);
    return Upd(x),x;
}
int nxt[N];
int Acs(int tx){

//  puts("NOW : ACS");          
    for(int x = tx,y = 0;x;Upd(y = x),x = p)Splay(x),u.rc = y;
//  puts("ACS : ENDED");    
//  Rep_0(i,n + 2)
//      printf("%d %d %d %d %d\n",i,t[i].par,t[i].ch[0],t[i].ch[1],t[i].sz);
    return Splay(tx);
}
void MRT(int x){x = Acs(x);u.Rev();}
void Link(int x,int y){MRT(x),p = y;}
void DB(){
    puts("DEBUGING--------------------------------------------");
    Rep_0(i,n + 2)
        printf("%d %d %d %d %d\n",i,t[i].par,t[i].ch[0],t[i].ch[1],t[i].sz);
    puts("END-------------------------------------------");
}
void Cut(int x,int y){MRT(x),y = Acs(y),o.lc = 0,u.par = 0;}
int main (){
//  freopen("a.txt","r",stdin);
    t[0].sz = 0;//TMD初始化 
    n = read();
    Repl(i,n)
        nxt[i] = read(),t[i].par = min(i + nxt[i],n + 1),nxt[i] = min(nxt[i] + i,n + 1);
//  DB();
    //Rep_0(i,n + 2)
    //  printf("%d %d\n",i,t[i].par);
    m = read();
//  DB();
    Rep(i,m)
    {
        int op = read(),x = read();
//      puts("-------------------------------------------------------");
        x ++;
        if(op & 1){
        //  DB();
            MRT(n + 1);//为什么不换根呢少年!!!!!! 
            x = Acs(x);
            printf("%d\n",ulfc.sz);
    //      Rep_0(i,n + 2)
    //          printf("lalala: %d %d\n",i,t[i].sz);
        }
        else {
            int k = read();
        //  DB(); 
            x = Acs(x);//printf("CUT:%d %d\n",x,x + k);
        //  DB();
        //  printf("%d NXT:%d\n",x,nxt[x]);
            Cut(x,nxt[x]);//你要CUT 的不是你的左儿子啊!!!! nxt数组爆了啊!!!! 
        //  printf("%d NXT : %d\n",x,nxt[x]);
        //  DB();
            Link(x,min(x + k,n + 1));
            nxt[x] = min(x + k,n + 1);
        //  printf("%d NXT : %d\n",x,nxt[x]);
        //  DB();
    //      Rep_0(i,n + 2)
    //          printf("***%d %d %d %d\n",i,t[i].par,t[i].ch[0],t[i].ch[1]);
    //      printf("%d %d\n",x,x + k);

        }
    }
    return 0;
}
/*
10
4 5 4 3 1 3 1 1 1 3 
5
2 0 2 
2 7 1 
2 5 7 
1 6 
2 5 6 

10
6 7 10 2 5 5 4 4 10 7 
10
2 2 1 
2 2 4 
*/
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151

大致错误犯了四个,第一个是忘记设置t[0]的sz为0,第二个是在询问的时候忘了换根,而至于第三个…… 
Cut错边了!!!! 
Cut的时候一定要清楚你是Cut什么边……显然我们是找到两个相邻的节点去Cut,那么我们需要存一下上一次的x能被弹飞到哪里去。 
第四个是比较2的错误,就是我nxt数组一开始取值为(i + nxt[i]),然而实际上那样会完美RE。 
应该改为min(i + nxt[i],n + 1)。 
模板就这样说完了。 
部分转载自百度文库的一篇文章叫做 
Link - Cut- Trees,写的很详细『当然可能有些人认为很废话』,感谢。 
题库网站的话: 
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=25242#overview 
略微注意一下就是sone1是TopTree…… 
这网站好多错……看着做吧#233 
略微调了一道题…… 
因为边带负权而我的快读一般都不带负数读入…… 
然后我就愉快地狗带了。 
http://www.lydsy.com/JudgeOnline/problem.php?id=2157 
BZOJ2157。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define Repl(i,n) for(int i = 1,ls; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define RDD(i,x,n) for(int i = x; i >= n; i --)
#define u t[x]
#define debug puts("**")
#define debug2 puts("404 NOT FOUND")
#define DEBUG puts("FREOPENING")
#define lc ch[0]
#define rc ch[1]
#define tc ch[ty]
#define vc ch[!ty]
#define v edge[i].to
#define ulfc t[u.lc]
#define o t[y]
#define urtc t[u.rc]
#define p u.par
using namespace std;
const int inf = 1 << 30;
const int N = 200005;
typedef long long ll;
int read(){
    char ch = getchar();
    while((ch < '0' || ch > '9')&& ch != '-')ch = getchar ();
    int x = 0,flag = 1;
    if(ch == '-')flag = -1,ch = getchar();
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar ();
    return x * flag;
}
int n,m,ed[N],idx;
struct LCT{
    int w,Max,Min,ch[2],par;
    ll sum;
    bool rev;
    bool tag;
    LCT(){w = sum = tag = 0;Max = -inf,Min = inf;}
    void Rev(){rev ^= 1;swap(lc,rc);}
    void TagR(){
        tag ^= 1;swap(Max,Min),w = -w,sum = - sum,Max = -Max,Min = -Min;
    }
    void TagW(int ps){
        sum -= w,w = ps,sum += w;
    }
}t[N << 2];
void DB(){/*puts("DEBUGING--------------------------------------------------");*/Rep_0(x,idx + 1)printf("x: %d sum: %lld w: %d lc: %d rc: %d p: %d\n",x,u.sum,u.w,u.lc,u.rc,p);}
void Upd(int x){
    u.sum = ulfc.sum + urtc.sum + u.w;
    u.Max = max(ulfc.Max,urtc.Max);
    if(x > n)u.Max = max(u.w,u.Max);
    u.Min = min(urtc.Min,ulfc.Min);
    if(x > n)u.Min = min(u.Min,u.w);
}
void Dw(int x){
    if(u.rev){
        ulfc.Rev(),urtc.Rev();u.rev ^= 1;
    }
    if(u.tag){
        ulfc.TagR(),urtc.TagR();u.tag ^=1;
    }
}
int sgn(int x){return t[p].lc == x ? 0 :t[p].rc == x ? 1 : -1;}
void sc(int x,int y,bool ty){u.tc = y;o.par = x;}
void Fix(int x){if(~sgn(x))Fix(p);Dw(x);}
void Rot(int x,bool ty){
    int y = p;
    if(~sgn(y))sc(o.par,x,sgn(y));
    else p = o.par;
    sc(y,u.vc,ty),sc(x,y,!ty),Upd(y);
}
int Splay(int x){
    Fix(x);
    int d0,d1,y;
    while((~(d0 = sgn(x)))){
        if(~(d1 = sgn(y = p)))Rot(d0 ^ d1 ? x : y,d0),Rot(x,d1);
        else Rot(x,d0);
    }
    return Upd(x),x;
}
int Acs(int tx){
    for(int x = tx,y = 0;x;Upd(y = x),x = p)Splay(x),u.rc = y;
    return Splay(tx);
}
void MRT(int x){Acs(x);u.Rev();}// 先Rev? 
void link(int x,int y){MRT(x),p = y;}
int main (){
//  freopen("lv.txt","r",stdin);
//  freopen("outp.txt","w",stdout);
    n = read();
    idx = n;
    Rep(i,n - 1){
        int a,b,c;
        ed[i] = ++ idx;
        a = read() + 1,b = read() + 1,c = read();
        link(a,idx),link(b,idx);
        t[idx].w = c;
        t[idx].Max = c;
        t[idx].Min = c;
        t[idx].sum = c;
    }
    m = read();
    char op[5];
    Rep(i,m){
        scanf("%s",op + 1);
        int a = read(),b = read();
        if(op[1] == 'C')
            Splay(ed[a]),t[ed[a]].w = b,Upd(ed[a]);
        else if(op[1] == 'N'){ //
            a ++ ,b ++;
            MRT(a);
            Acs(b);
            t[b].TagR();
        }
        else{  // Sum
            a ++ , b ++;
            MRT(a);
            Acs(b);
            if(op[1] == 'S')//Sum
                printf("%lld\n",t[b].sum);
            else if(op[2] == 'I')// Min
                printf("%d\n",t[b].Min);
            else if(op[2] == 'A')
                printf("%d\n",t[b].Max);
        }
    }
    return 0;
}
/*
5
0 1 32
0 4 45
0 3 37
1 2 76
3
N 0 3
SUM 0 1
MIN 0 2
*/
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145

其实这道题没必要用LCT,然而就是想练模板…… 
然后还有一道题。

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#define Rep(i,n) for(int i = 1; i <= n ; i ++)
#define RepG(i,x) for(int i = head[x] ;~ i ; i = edge[i].next)
#define Rep_d(i,n) for(int i = n ; i > 0 ; i --)
#define Rep_0(i,n) for(int i = 0 ; i < n ; i ++)
#define RD(i,x,n) for(int i = x; i <= n ; i ++)
#define CLR(a,b) memset(a,b,sizeof(a))
#define RDD(i,x,n) for(int i = x; i >= n; i --)
#define lc ch[0]
#define rc ch[1]
#define tc ch[ty]
#define vc ch[!ty]
#define u t[x]
#define o t[y]
#define p t[x].par
#define v edge[i].to
#define ulfc t[u.lc]
#define urtc t[u.rc]
const int N = 10005;
using namespace std;
const int inf = 1 << 30;
typedef long long ll;
inline int read(){
    char ch = getchar();
    while((ch < '0' || ch > '9') && ch != '-')ch = getchar ();
    int x = 0;
    bool flag = 1;
    if(ch == '-')ch = getchar(),flag = 0;
    while(ch >= '0' && ch <= '9')x = 10 * x + ch - '0',ch = getchar ();
    return flag ? x : -x;
}
int n,m;
struct LCT{int ch[2],par;bool rev;void Rev(){rev ^= 1;swap(lc,rc);}}t[N];
inline int sgn(int x){return t[p].ch[0] == x ? 0: t[p].ch[1] == x ? 1 : -1;}
inline void sc(int x,int y,bool ty){o.par = x;u.tc = y;}
inline void Upd(int x){;}
inline void Rot(int x,bool ty){
    int y ;
    if(~sgn(y = p))sc(o.par,x,sgn(y));
    else p = o.par;
    sc(y,u.vc,ty),sc(x,y,!ty),Upd(y);
}
inline void Dw(int x){
    if(u.rev)ulfc.Rev(),urtc.Rev(),u.rev ^= 1;
}
inline void Fix(int x){if(~sgn(x))Fix(p);Dw(x);}
int Splay(int x){
    Fix(x);
    int d0,d1,y;
    while(~(d0 = sgn(x))){
        if(~(d1 = sgn(y = p)))
            Rot(d0 ^ d1 ? x : y, d0),Rot(x,d1);
        else Rot(x,d0);
    }
    return Upd(x),x;
}
int Acs(int tx){for(int x = tx,y = 0 ;x;Upd(y = x),x = p)Splay(x),u.rc = y;return Splay(tx);}
inline void MRT(int x){Acs(x);u.Rev();}
inline void Link(int x,int y){MRT(x);p = y;} 
inline void Cut(int x,int y){MRT(x);Acs(y);o.lc = 0,u.par = 0;}
inline bool Find(int x,int y){while(p)x = p;while(o.par)y = o.par;return x == y;} 
int main (){
    n = read();
    m = read();
    Rep(i,m)
    {
        char op[15];
        scanf("%s",op + 1);
        int a = read(),b = read();
        if(op[1] == 'Q')
            puts(Find(a,b) ? "Yes" : "No");
        else if(op[1] == 'C')
            Link(a,b);
        else if(op[1] == 'D')
            Cut(a,b); 
    }
    return 0;
}



 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84

洞穴勘测Cave…… 
很水的一道题……也就是练模板了。 
下面开始做真正的LCT吧,另开一文好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值