#LCT,并查集#洛谷 10658 BZOJ2959 长跑
分析
考虑用两个并查集来维护,第一个并查集维护连通性,而第二个并查集维护边双连通分量,也就是如果两个点位于不同的边双就把它们合到一起,
查询就是缩点后两点路径点权之和,可以用 LCT 维护,注意父亲变成了边双上的父亲而不是原树上的父亲。
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=150101; int n,m,a[N],f[N];
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
struct Union_Set{
int f[N],w[N];
int getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
}T;
struct Splay{
int w[N],son[N][2],fat[N],stac[N],TOP; bool rev[N];
bool unroot(int x){return son[T.getf(fat[x])][0]==x||son[T.getf(fat[x])][1]==x;}
bool Is_R(int x){return son[T.getf(fat[x])][1]==x;}
void pup(int x){w[x]=w[son[x][0]]+w[son[x][1]]+T.w[x];}
void Rev(int x){swap(son[x][0],son[x][1]),rev[x]^=1;}
void pdown(int x){
if (rev[x]){
if (son[x][0]) Rev(son[x][0]);
if (son[x][1]) Rev(son[x][1]);
rev[x]=0;
}
}
void rotate(int x){
int Fa=T.getf(fat[x]),FFa=T.getf(fat[Fa]),wh=Is_R(x),t=son[x][wh^1];
if (unroot(Fa)) son[FFa][Is_R(Fa)]=x;
son[x][wh^1]=Fa,son[Fa][wh]=t;
if (t) fat[t]=Fa;
fat[Fa]=x,fat[x]=FFa;
pup(Fa),pup(x);
}
void splay(int x){
int y=x; stac[TOP=1]=y;
while (unroot(y)) stac[++TOP]=y=T.getf(fat[y]);
for (;TOP;--TOP) pdown(stac[TOP]);
for (;unroot(x);rotate(x)){
int Fa=T.getf(fat[x]);
if (unroot(Fa)) rotate((Is_R(x)^Is_R(Fa))?x:Fa);
}
}
void Access(int x){
for (int y=0;x;x=T.getf(fat[y=x]))
splay(x),son[x][1]=y,pup(x);
}
void Make_root(int x){Access(x),splay(x),Rev(x);}
int Find_root(int x){
Access(x),splay(x);
for (;son[x][0];x=son[x][0]) pdown(x);
splay(x);
return x;
}
void Split(int x,int y){Make_root(x),Access(y),splay(y);}
void Link(int x,int y){Make_root(x); if (Find_root(y)!=x) fat[x]=y;}
}Tre;
int getf(int u){return f[u]==u?u:f[u]=getf(f[u]);}
void Merge(int rt,int x){
if (T.getf(rt)!=T.getf(x)){
T.w[T.getf(rt)]+=T.w[T.getf(x)];
T.f[T.getf(x)]=T.f[T.getf(rt)];
}
if (Tre.son[x][0]) Merge(rt,Tre.son[x][0]);
if (Tre.son[x][1]) Merge(rt,Tre.son[x][1]);
}
int main(){
n=iut(); m=iut();
for (int i=1;i<=n;++i) T.w[i]=a[i]=iut(),T.f[i]=f[i]=i;
while (m--){
int opt=iut(),x=iut(),y=iut();
switch (opt){
case 1:{
x=T.getf(x),y=T.getf(y);
if (getf(x)!=getf(y)){
f[getf(x)]=getf(y);
Tre.Link(x,y);
}else if (x!=y){
Tre.Split(x,y);
Merge(y,y);
Tre.pup(y);
}
break;
}
case 2:{
int u=T.getf(x);
Tre.Make_root(u);
T.w[u]+=y-a[x],a[x]=y;
Tre.pup(u);
break;
}
case 3:{
x=T.getf(x),y=T.getf(y);
if (getf(x)!=getf(y)) putchar('-'),putchar(49);
else Tre.Split(x,y),print(Tre.w[y]);
putchar(10);
break;
}
}
}
return 0;
}

浙公网安备 33010602011771号