標籤:
又一道LCT模板題。
如何找是不是在同一棵樹上?只要找深度最小的點是不是相同的點即可。
也就是splay最左邊的那個點。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define maxv 10050#define maxe 20050using namespace std;int n,m,fath[maxv],size[maxv],tree[maxv][3],x,y,rev[maxv];int stack[maxv],top=0;char s[20];bool isroot(int x){ return tree[fath[x]][1]!=x&&tree[fath[x]][2]!=x;}void pushdown(int x){ if (rev[x]) { int ls=tree[x][1],rs=tree[x][2]; rev[ls]^=1;rev[rs]^=1;rev[x]=0; swap(tree[x][1],tree[x][2]); }}void pushup(int x){ int ls=tree[x][1],rs=tree[x][2]; size[x]=size[ls]+size[rs]+1;}void rotate(int x){ int y=fath[x],z=fath[y],l,r; if (tree[y][1]==x) l=1;else l=2; r=3-l; if (!isroot(y)) { if (tree[z][1]==y) tree[z][1]=x; else tree[z][2]=x; } fath[x]=z;fath[y]=x;fath[tree[x][r]]=y; tree[y][l]=tree[x][r];tree[x][r]=y; pushup(y);pushup(x);}void splay(int x){ top=0; stack[++top]=x; for (int i=x;!isroot(i);i=fath[i]) stack[++top]=fath[i]; for (int i=top;i>=1;i--) pushdown(stack[i]); while (!isroot(x)) { int y=fath[x],z=fath[y]; if (!isroot(y)) { if ((tree[y][1]==x)^(tree[z][1]==y)) rotate(x); else rotate(y); } rotate(x); }}void access(int x){ int regis=0; while (x) { splay(x); tree[x][2]=regis; regis=x;x=fath[x]; }}void makeroot(int x){ access(x); splay(x); rev[x]^=1;}void link(){ scanf("%d%d",&x,&y); makeroot(x); fath[x]=y; splay(x);}void cut(){ scanf("%d%d",&x,&y); makeroot(x);access(y); splay(y);tree[y][1]=0;fath[x]=0;}int find(int x){ access(x);splay(x); int y=x; while (tree[y][1]) y=tree[y][1]; return y;}void query(){ scanf("%d%d",&x,&y); int u=find(x),v=find(y); if (u==v) printf("Yes\n"); else printf("No\n");}int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) size[i]=1; for (int i=1;i<=m;i++) { scanf("%s",s); if (s[0]==‘C‘) link(); else if (s[0]==‘D‘) cut(); else if (s[0]==‘Q‘) query(); } return 0;}
BZOJ 2049 洞穴勘測