• 【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]<<'
    ';
    		}
    	}
    }
    
  • 相关阅读:
    无废话XML阅读笔记(三)
    ____ To All Girls & Boys
    FDT注册码
    无废话XML阅读笔记(五)
    无废话XML阅读笔记(一)
    物理运动学公式汇总
    flash编译器错误查询表
    入秋了,给大家一些生活小常识
    12年
    linux 自动上传程序
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145552.html
Copyright © 2020-2023  润新知