LCT 并查集
LCT维护双连通分量。
如果没有1操作可以Tarjan+树剖水过,现在是动态的话就用LCT维护。
当 A A 和不连通时直接连起来。当 A A 和已经连通时,把它们所在的双连通分量缩到一个点上。具体操作为先把 A A 和搞到同一个Splay里,然后遍历Splay,用并查集把所有点都缩到一个点上去并把权值赋给它。
判断是否连通可以直接用LCT,然而我太菜所以 T了就又开了一个并查集。
代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 150005
#define F inline
#define V F void
using namespace std;
typedef long long LL;
struct tree{ int fa,to[2],v; LL x; bool f; }t[N];
int n,m,tp,w[N],f1[N],f2[N],stk[N]; LL tmp;
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
return l==r?EOF:*l++;
}
F int _read(){
int x=0; char ch=readc();
while (!isdigit(ch)) ch=readc();
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x;
}
V writec(LL x){ if (x>9) writec(x/10); putchar(x%10+48); }
V _write(LL x){ writec(x),puts(""); }
int findfa(int *fa,int x){ return x==fa[x]?x:fa[x]=findfa(fa,fa[x]); }
#define f(x) findfa(f2,t[x].fa)
#define rt(x) (t[f(x)].to[0]!=(x)&&t[f(x)].to[1]!=(x))
V pshp(int x){ t[x].x=t[x].v+t[t[x].to[0]].x+t[t[x].to[1]].x; }
V pshd(int x){
if (!t[x].f) return; int &l=t[x].to[0],&r=t[x].to[1];
t[x].f=0,swap(l,r),t[l].f^=1,t[r].f^=1;
}
V rtt(int x){
int y=f(x),z=f(y),l=t[y].to[0]==x;
if (!rt(y)) t[z].to[t[z].to[0]!=y]=x;
t[x].fa=z,t[y].fa=x,t[t[x].to[l]].fa=y;
t[y].to[l^1]=t[x].to[l],t[x].to[l]=y;
pshp(y),pshp(x);
}
V splay(int x){
for (int i=stk[tp=1]=x;!rt(i);i=f(i))
stk[++tp]=f(i);
while (tp) pshd(stk[tp--]);
for (int y=f(x),z=f(y);!rt(x);rtt(x),y=f(x),z=f(y))
if (!rt(y)) rtt(t[z].to[0]==y^t[y].to[0]==x?x:y);
}
V ccss(int x){ for (int i=0;x;i=x,x=f(x)) splay(x),t[x].to[1]=i,pshp(x); }
V mkrt(int x){ ccss(x),splay(x),t[x].f^=1; }
V mrg(int x,int y){
int &l=t[x].to[0],&r=t[x].to[1];
if (l) t[y].v+=t[l].v,mrg(l,y);
if (r) t[y].v+=t[r].v,mrg(r,y);
f2[x]=y,l=r=0;
}
V sprt(int x,int y){ mkrt(x),ccss(y),splay(y); }
V lnk(int x,int y){
int fx=findfa(f1,x),fy=findfa(f1,y);
if (findfa(f1,x)!=findfa(f1,y))
mkrt(x),t[x].fa=y,f1[f1[x]]=f1[y];
else sprt(x,y),mrg(y,y),pshp(y);
}
F LL srch(int x,int y){
if (findfa(f1,x)!=findfa(f1,y)) return -1;
sprt(x,y); return t[y].x;
}
int main(){
n=_read(),m=_read();
for (int i=1;i<=n;i++)
w[i]=t[i].v=_read(),f1[i]=f2[i]=i,pshp(i);
while (m--){
int f=_read(),x=_read(),y=_read(),fx=findfa(f2,x);
if (f==1) lnk(fx,findfa(f2,y));
else if (f==2) mkrt(fx),t[fx].v+=y-w[x],w[x]=y,pshp(fx);
else (tmp=srch(fx,findfa(f2,y)))!=-1?_write(tmp):(void)puts("-1");
}
return 0;
}