【题意】
给你一个森林,要求支持动态加边删边,并会询问在某一个时刻两点是否联通。
【题解】
裸的lct,模版题。第一次写对lct,没写过真的难写。。。。
【代码】
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 using namespace std; 5 const int N=10005; 6 int n,Q,x,y; 7 int c[N][2],fa[N],rev[N],a[N]; 8 bool isroot(int x) 9 { 10 return c[fa[x]][0]!=x && c[fa[x]][1]!=x; 11 } 12 void down(int x) 13 { 14 if (rev[x]) 15 { 16 rev[x]=0; 17 rev[c[x][0]]^=1; 18 rev[c[x][1]]^=1; 19 swap(c[x][0],c[x][1]); 20 } 21 } 22 void rotate(int x) 23 { 24 int y=fa[x],z=fa[y],l,r; 25 if (c[y][0]==x) l=0;else l=1;r=1^l; 26 if (!isroot(y)) if (c[z][0]==y) c[z][0]=x;else c[z][1]=x; 27 fa[x]=z; 28 c[y][l]=c[x][r];fa[c[x][r]]=y; 29 c[x][r]=y;fa[y]=x; 30 } 31 void splay(int x) 32 { 33 int y=x,z,cnt=0; 34 while (!isroot(y)) 35 { 36 a[++cnt]=y; 37 y=fa[y]; 38 } 39 a[++cnt]=y; 40 while (cnt--) down(a[cnt+1]); 41 while (!isroot(x)) 42 { 43 y=fa[x];z=fa[y]; 44 if (!isroot(y)) 45 if (c[y][0]==x ^ c[z][0]==y) 46 rotate(x); 47 else rotate(y); 48 rotate(x); 49 } 50 } 51 void access(int x) 52 { 53 int t=0; 54 while (x) 55 { 56 splay(x); 57 c[x][1]=t; 58 t=x;x=fa[x]; 59 } 60 } 61 void mt(int x) 62 { 63 access(x); 64 splay(x); 65 } 66 void make_root(int x) 67 { 68 mt(x); 69 rev[x]^=1; 70 down(x); 71 } 72 void link(int x,int y) 73 { 74 make_root(x); 75 fa[x]=y; 76 } 77 void cut(int x,int y) 78 { 79 make_root(x); 80 mt(y); 81 fa[x]=c[y][0]=0; 82 } 83 bool solve(int x,int y) 84 { 85 make_root(x); 86 access(y); 87 splay(x); 88 int z=y; 89 while (!isroot(y) && y!=fa[y]) y=fa[y]; 90 splay(z); 91 if (x==y) return 1; 92 else return 0; 93 } 94 int main() 95 { 96 scanf("%d%d",&n,&Q); 97 char str[10]; 98 while (Q--) 99 { 100 scanf("%s%d%d",str,&x,&y); 101 if (str[0]=='C') link(x,y); 102 else if (str[0]=='D') cut(x,y); 103 else if (solve(x,y)) puts("Yes");else puts("No"); 104 } 105 return 0; 106 }