题目:https://www.luogu.org/problemnew/show/P3690
自己竟然从没有钻研过LCT上的连通性问题!
于是被最后一个点卡了,似乎因为 find 函数只能找出连通性而不能判断有没有直接相连的边;
所以还是直接在 cut 函数里判断一下好了。
(注:第9个点时T时不T的,不想去管它了。)
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const maxn=3e5+5; int n,m,fa[maxn],c[maxn][3],sum[maxn],w[maxn],rev[maxn],sta[maxn],top; bool isroot(int x){return c[fa[x]][0]!=x && c[fa[x]][1]!=x;} void pushup(int x) { sum[x]=(sum[c[x][0]]^sum[c[x][1]]^w[x]); } void reverse(int x) { if(rev[x]) { rev[c[x][0]]^=1; rev[c[x][1]]^=1; rev[x]=0; swap(c[x][0],c[x][1]); } } void rotate(int x) { int y=fa[x],z=fa[y],d=(c[y][1]==x); if(!isroot(y))c[z][c[z][1]==y]=x; fa[x]=z; fa[y]=x; fa[c[x][!d]]=y; c[y][d]=c[x][!d]; c[x][!d]=y; pushup(y); pushup(x); } void splay(int x) { sta[top=1]=x; for(int i=x;!isroot(i);i=fa[i])sta[++top]=fa[i]; for(;top;top--)reverse(sta[top]); for(;!isroot(x);rotate(x)) { int y=fa[x],z=fa[y]; if(isroot(y))continue; ((c[y][0]==x)^(c[z][0]==y))?rotate(x):rotate(y); } } void access(int x) { for(int t=0;x;c[x][1]=t,pushup(x),t=x,x=fa[x])splay(x); } void makeroot(int x) { access(x); splay(x); rev[x]^=1; } void link(int x,int y) { makeroot(x); fa[x]=y; } void query(int x,int y) { makeroot(x); access(y); splay(y); } void cut(int x,int y) { query(x,y); if(c[y][0]!=x)return;//! fa[x]=0; c[y][0]=0; } int find(int x) { access(x); splay(x); while(c[x][0])x=c[x][0]; return x; } void change(int u,int t) { makeroot(u); w[u]=t; pushup(u); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&w[i]); for(int i=1,op,x,y;i<=m;i++) { scanf("%d%d%d",&op,&x,&y); if(op==0){query(x,y); printf("%d ",sum[y]);} if(op==1) { if(find(x)==find(y))continue; link(x,y); } if(op==2) { // if(find(x)!=find(y))continue; cut(x,y); } if(op==3)change(x,y); } return 0; } /* 5 6 1 2 3 4 5 1 1 2 1 2 3 1 3 4 1 4 5 2 1 5 0 1 5 1 */