【BZOJ2959】—长跑(LCT维护双连通分量+并查集)

传送门


LCT维护双连通分量

每次连边的时候判一下两边连通性
如果联通就把两点之间的环缩成一个新节点
询问就是两点之间距离和
由于findrtfindrt很慢就写一个并查集维护一下

#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';
		}
	}
}
posted @ 2019-05-03 16:25  Stargazer_cykoi  阅读(149)  评论(0编辑  收藏  举报