显然,如果没有环的话,走的就是两点之间的唯一路径。直接用lct维护即可。
但是现在有环,显然可以把环缩到一个点,那么用并查集维护一下即可。剩下的使用lct即可。
嘴巴AC还是很简单的。。。
AC代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define N 150005 using namespace std; int n,m,a[N],c[N][2],fa[N],sum[N],val[N]; bool rev[N]; int read(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x; } struct frt{ int anc[N]; void pfs(){ int i; for (i=1; i<=n; i++) anc[i]=i; } int getanc(int x){ return (x==anc[x])?x:anc[x]=getanc(anc[x]); } }f1,f2; bool isrt(int x){ return c[fa[x]][0]!=x && c[fa[x]][1]!=x; } void maintain(int x){ sum[x]=val[x]+sum[c[x][0]]+sum[c[x][1]]; } void dn(int x){ if (x && rev[x]){ rev[c[x][0]]^=1; rev[c[x][1]]^=1; swap(c[x][0],c[x][1]); rev[x]=0; } } void pushdown(int x){ if (!isrt(x)) pushdown(fa[x]); dn(x); } void rotate(int x){ int y=fa[x],z=fa[y],l=(c[y][0]==x)?0:1,r=l^1; if (!isrt(y)) if (c[z][0]==y) c[z][0]=x; else c[z][1]=x; fa[x]=z; fa[y]=x; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; maintain(y); maintain(x); } void splay(int x){ pushdown(x); int y,z; while (!isrt(x)){ y=fa[x]; z=fa[y]; if (!isrt(y)) if ((c[y][0]==x)^(c[z][0]==y)) rotate(x); else rotate(y); rotate(x); } } void accs(int x){ int y=0; for (; x; y=x,x=f2.getanc(fa[x])){ splay(x); c[x][1]=y; fa[y]=x; maintain(x); } } void makert(int x){ accs(x); splay(x); rev[x]^=1; } void link(int x,int y){ makert(x); fa[x]=y; } void ins(int x,int y){ x=f2.getanc(x); splay(x); val[x]+=y; maintain(x); } void merge(int x,int y){ dn(x); f2.anc[x]=y; if (x!=y) val[y]+=val[x]; if (c[x][0]) merge(c[x][0],y); if (c[x][1]) merge(c[x][1],y); c[x][0]=c[x][1]=0; } int main(){ n=read(); m=read(); int i,x,y,u,v,k; f1.pfs(); f2.pfs(); for (i=1; i<=n; i++){ a[i]=read(); ins(i,a[i]); } while (m--){ k=read(); x=read(); y=read(); if (k==1){ x=f2.getanc(x); y=f2.getanc(y); if (x!=y){ u=f1.getanc(x); v=f1.getanc(y); if (u!=v){ link(x,y); f1.anc[u]=v; } else{ makert(x); accs(y); splay(y); merge(y,y); } } } else if (k==2){ ins(x,y-a[x]); a[x]=y; } else{ x=f2.getanc(x); y=f2.getanc(y); u=f1.getanc(x); v=f1.getanc(y); if (u!=v) puts("-1"); else{ makert(x); accs(y); splay(y); printf("%d\n",sum[y]); } } } return 0; }
by lych
2016.4.13