【BZOJ2959】—长跑(LCT维护双连通分量+并查集)
LCT维护双连通分量
每次连边的时候判一下两边连通性
如果联通就把两点之间的环缩成一个新节点
询问就是两点之间距离和
由于很慢就写一个并查集维护一下
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ob,*ib;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
const int N=300005;
int n,m,val[N],son[N][2],fa[N],bel[N],fath[N],a[N],b[N],rev[N],q[N],top;
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline int findset(int x){
return bel[x]==x?x:bel[x]=findset(bel[x]);
}
inline int find(int x){
return fath[x]==x?x:fath[x]=find(fath[x]);
}
inline bool isrt(int u){
if(!fa[u])return 1;
int f=findset(fa[u]);
return (lc(f)!=u&&rc(f)!=u);
}
inline bool isrc(int u){
return rc(findset(fa[u]))==u;
}
inline void pushup(int u){
val[u]=a[u];
if(lc(u))val[u]+=val[lc(u)];
if(rc(u))val[u]+=val[rc(u)];
}
inline void pushdown(int u){
if(!rev[u])return;
if(lc(u))rev[lc(u)]^=1;
if(rc(u))rev[rc(u)]^=1;
swap(lc(u),rc(u)),rev[u]=0;
}
inline void rotate(int v){
int u=fa[v],z=fa[u];
int t=rc(u)==v;
if(!isrt(u))son[z][rc(z)==u]=v;
fa[v]=z;
fa[son[v][t^1]]=u,son[u][t]=son[v][t^1];
fa[u]=v,son[v][t^1]=u;
pushup(u),pushup(v);
}
inline void splay(int u){
q[q[0]=1]=u;
for(int v=u;!isrt(v);v=findset(fa[v]))q[++q[0]]=findset(fa[v]);
for(int i=q[0];i;i--)pushdown(q[i]),fa[q[i]]=findset(fa[q[i]]);
while(!isrt(u)){
if(!isrt(fa[u]))
isrc(u)==isrc(fa[u])?rotate(fa[u]):rotate(u);
rotate(u);
}
pushup(u);
}
inline void access(int u){
for(int v=0;u;v=u,u=findset(fa[u])){
splay(u);
rc(u)=v,fa[v]=u;
pushup(u);
}
}
inline void makert(int u){
access(u),splay(u),rev[u]^=1;
}
inline void link(int u,int v){
makert(u),fa[u]=v,pushdown(v),pushup(v);
}
inline void merge(int u,int v){
bel[findset(u)]=findset(v),pushdown(u);
if(v!=u)a[v]+=a[u];
if(lc(u))merge(lc(u),v);
if(rc(u))merge(rc(u),v);
lc(u)=rc(u)=0;
}
int main(){
n=read(),m=read();
for(int i=1;i<=n;i++){
a[i]=b[i]=read(),bel[i]=fath[i]=i;
}
while(m--){
int op=read(),u=read(),v=read();
if(op==1){
u=findset(u),v=findset(v);
if(u==v)continue;
int f1=find(u),f2=find(v);
if(f1!=f2)fath[f1]=f2,link(u,v);
else {
makert(u),access(v),splay(v);
merge(v,v),pushup(v);
}
}
if(op==2){
int f=findset(u);
access(f),splay(f),a[f]+=v-b[u],b[u]=v,pushup(f);
}
if(op==3){
int f1=findset(u),f2=findset(v);
if(find(f1)!=find(f2)){puts("-1");continue;}
makert(f1),access(f2),splay(f2);cout<<val[f2]<<'\n';
}
}
}