[SDOI2008]洞穴勘测
SOL: LCT维护联通性,当然,启发式合并并查集可能会更好写。
#include<bits/stdc++.h> #define N 200007 int rev[N],ch[N][2],f[N],q[N],top; using namespace std; inline void push_down(int x) { if (rev[x]) { rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]=0; swap(ch[x][0],ch[x][1]); } } inline bool rt(int x){ return ch[f[x]][0]!=x&&ch[f[x]][1]!=x; } inline void ro(int x){ int y=f[x],z=f[y],kind=(ch[y][0]==x); if (!rt(y)) ch[z][ch[z][1]==y]=x; f[ch[x][kind]]=y; f[y]=x; f[x]=z; ch[y][kind^1]=ch[x][kind]; ch[x][kind]=y; } //inline void splay(int x){ inline void splay(int x) { q[top=1]=x; for (int i=x;!rt(i);i=f[i]) q[++top]=f[i]; while (top) push_down(q[top--]); while (!rt(x)) { int y=f[x],z=f[y]; if (!rt(y)) { if (ch[y][0]==x^ch[z][0]==y) ro(x); else ro(y); } ro(x); } // push_up(x); } inline void access(int x) { for (int t=0;x;t=x,x=f[x]) splay(x),ch[x][1]=t; } inline void make_rt(int x) { access(x); splay(x); rev[x]^=1; } inline void link(int x,int y){ make_rt(x); f[x]=y; } inline int find(int x){ access(x); splay(x); while (ch[x][0]) push_down(x),x=ch[x][0]; return x; } inline void cut(int x,int y){ make_rt(x); if (find(y)==x&&f[x]==y&&!ch[x][1]) f[x]=ch[y][0]=0; } int n,m,x,y; char as[19]; signed main () { // freopen("a.in","r",stdin); scanf("%d%d",&n,&m); while (m--) { scanf("%s",as); scanf("%d%d",&x,&y); if (as[0]=='Q') { printf("%s\n",(find(x)^find(y))?"No":"Yes"); } else if (as[0]=='C') { if (find(x)^find(y)) link(x,y); } else { if (find(x)==find(y)) cut(x,y); } } }