题意:
一些点,三种操作:点与点连边、点与点分离、询问两个点是否连通。
题解:
比上面那道还弱的LCT,只要注意记得翻转就行。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define maxn 50000 6 using namespace std; 7 8 int fa[maxn],ch[maxn][2],rev[maxn]; 9 void pushdown(int x){ 10 if(rev[x]){ 11 swap(ch[x][0],ch[x][1]); if(ch[x][0])rev[ch[x][0]]^=1; if(ch[x][1])rev[ch[x][1]]^=1; rev[x]^=1; 12 } 13 } 14 bool is_root(int x){ 15 if(x==0||fa[x]==0)return 1; return x!=ch[fa[x]][0]&&x!=ch[fa[x]][1]; 16 } 17 void rotate(int x){ 18 if(x==0||is_root(x))return; 19 int a1=fa[x],a2=fa[fa[x]],a3; bool b1=(x==ch[a1][1]),b2=(a1==ch[a2][1]),b3=is_root(a1); a3=ch[x][!b1]; 20 if(!b3)ch[a2][b2]=x; fa[x]=a2; ch[a1][b1]=a3; fa[a3]=a1; ch[x][!b1]=a1; fa[a1]=x; 21 } 22 int dts,dt[maxn],y; 23 void splay(int x){ 24 if(x==0)return; dts=0; y=x; while(! is_root(y))dt[++dts]=y,y=fa[y]; 25 dt[++dts]=y; while(dts)pushdown(dt[dts]),dts--; 26 while(! is_root(x)){ 27 if(! is_root(fa[x]))(x==ch[x][1])^(fa[x]==ch[fa[fa[x]]][1])?rotate(x):rotate(fa[x]); 28 rotate(x); 29 } 30 } 31 int access(int x){ 32 if(x==0)return 0; int t=0; 33 while(x){splay(x); ch[x][1]=t; if(t)fa[t]=x; t=x; x=fa[x];} 34 return t; 35 } 36 void link(int x,int y){ 37 if(x==0||y==0)return; access(x); splay(x); rev[x]^=1; fa[x]=y; 38 } 39 void cut(int x,int y){ 40 if(x==0||y==0)return; access(x); splay(x); rev[x]^=1; access(y); splay(y); ch[y][0]=fa[x]=0; 41 } 42 int find(int x){ 43 access(x); splay(x); while(ch[x][0])x=ch[x][0]; return x; 44 } 45 int n,m; char s[10]; 46 int main(){ 47 scanf("%d",&n); inc(i,1,n)fa[i]=ch[i][0]=ch[i][1]=0; scanf("%d",&m); 48 inc(i,1,m){ 49 int a,b; scanf("%s%d%d",s,&a,&b); 50 if(s[0]=='C')link(a,b); 51 if(s[0]=='D')cut(a,b); 52 if(s[0]=='Q')find(a)==find(b)?puts("Yes"):puts("No"); 53 } 54 return 0; 55 }
20160422