题解:
lct
和上一题差不多
这一题还要判断是否有链接
其实直接并查集判断就可以了
代码:
#pragma GCC optimize(2) #include<bits/stdc++.h> const int N=100010; using namespace std; int read() { int x=0;char ch=getchar(); for (;ch<‘0‘||ch>‘9‘;ch=getchar()); for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar())x=x*10+ch-‘0‘; return x; } int n,m,top,cnt,c[N][2],fa[N],size[N],q[N],rev[N],f[N],sum[N],val[N],at[N],mt[N]; int isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;} void update(int x) { int l=c[x][0],r=c[x][1]; sum[x]=sum[l]+sum[r]+val[x]; size[x]=size[l]+size[r]+1; } void pushdown(int x) { int l=c[x][0],r=c[x][1]; if (rev[x]) { rev[x]^=1;rev[l]^=1;rev[r]^=1; swap(c[x][0],c[x][1]); } } void rotate(int x) { int y=fa[x],z=fa[y],l,r; l=(c[y][1]==x);r=l^1; if (!isroot(y))c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y);update(x); } void down(int x){if (!isroot(x))down(fa[x]);pushdown(x);} void splay(int x) { down(x); for (int y=fa[x];!isroot(x);rotate(x),y=fa[x]) if (!isroot(y))rotate((c[y][0]==x)==(c[fa[y]][0]==y)?y:x); } void access(int x) { for(int t=0;x;t=x,x=fa[x]) { splay(x); c[x][1]=t; update(x); } } void makeroot(int x){access(x);splay(x);rev[x]^=1;} void split(int x,int y){makeroot(y);access(x);splay(x);} void link(int x,int y){makeroot(x);fa[x]=y;} int find(int x){if (x==f[x])return f[x];return f[x]=find(f[x]);} int main() { n=read(); for (int i=1;i<=n;i++)val[i]=sum[i]=read(),f[i]=i,size[i]=1; m=read();char ch[50]; while(m--) { scanf("%s",ch); int u=read(),v=read(); if (ch[0]==‘b‘) { if (f[find(u)]==f[find(v)])puts("no"); else puts("yes"),link(u,v),f[find(u)]=f[find(v)]; } if (ch[0]==‘p‘) { val[u]=v; makeroot(u); } if (ch[0]==‘e‘) { if (f[find(u)]!=f[find(v)]) { puts("impossible"); continue; } split(u,v); printf("%d\n",sum[u]); } } return 0; }