• bzoj2959 长跑


    https://darkbzoj.tk/problem/2959

    和那个bzoj4998 星球联盟比较像,都是用并查集加 lct 来维护双连通性

    其实就是要处理环,因为如果无环,那么要求的值就是路径上所有点的值
    而有了环,由于没有断边操作,那么就把整个环缩成一个点,用并查集来维护
    还有一个并查集用来维护连通性(上一行说的是维护双连通性的)

    更具体的,就是如果连边时给定两个点 ((x,y)),它们已经连通了,就在 lct 中把它们的链 split 出来,把这些点的权值都加到 (u,v) 的其中一个点上,维护双连通性的并查集父亲也指向那个点
    这样由于 lct 中套了一个并查集,每次要把 lct 里的点 find 一下再进行操作

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<map>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	register int x=0;register int y=1;
    	register char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    #define N 200005
    struct tr{
    	tr *fa,*son[2];
    	int sum,val,tag;
    	tr *setfa;
    }*null,dizhi[N],*pos[N];
    int fa[N];
    inline tr *find(tr *k){return (k->setfa==k)?k:k->setfa=find(k->setfa);}
    inline int find(int k){return k==fa[k]?k:fa[k]=find(fa[k]);}
    int val[N];
    #define ident(tree,fa) (fa->son[1]==tree)
    #define notroot(tree) (find(tree->fa)->son[0]==tree||find(tree->fa)->son[1]==tree)
    #define pushup(tree) (tree->sum=tree->val+tree->son[0]->sum+tree->son[1]->sum)
    inline void connect(tr *tree,tr *fa,int k){tree->fa=fa;fa->son[k]=tree;}
    inline void pushdown(tr *tree){
    	if(!tree->tag) return;
    	tree->tag=0;
    	std::swap(tree->son[0],tree->son[1]);
    	tree->son[0]->tag^=1;tree->son[1]->tag^=1;
    }
    inline void rotate(tr *tree){
    	tr *fa=find(tree->fa),*faa=find(fa->fa);
    	pushdown(fa);pushdown(tree);
    	int k=ident(tree,fa);
    	connect(tree->son[k^1],fa,k);
    	tree->fa=faa;
    	if(notroot(fa)) faa->son[ident(fa,faa)]=tree;
    	connect(fa,tree,k^1);
    	pushup(fa);pushup(tree);
    }
    inline void splay(tr *tree){
    	reg tr *fa,*faa;
    	while(notroot(tree)){
    		fa=find(tree->fa);faa=find(fa->fa);
    		if(notroot(fa)) ident(fa,faa)^ident(tree,fa)?rotate(tree):rotate(fa);
    		rotate(tree);
    	}
    }
    inline void access(reg tr *x){
    	for(reg tr *lastx=null;x!=null;lastx=x,x=find(x->fa)){
    		pushdown(x);
    		splay(x);
    		x->son[1]=lastx;pushup(x);
    	}
    }
    inline void makeroot(tr *tree){
    	access(tree);
    	splay(tree);tree->tag^=1;
    }
    int ans;
    void dfs(tr *x,tr *pre){
    	if(x==null) return;
    	if(x!=pre) x->setfa=pre;
    	pushdown(x);
    	dfs(x->son[0],pre);dfs(x->son[1],pre);
    }
    inline void link(tr *x,tr *y){
    	makeroot(x);
    	x->fa=y;
    }
    inline void Link(int uu,int vv){
    	tr *x=find(pos[uu]),*y=find(pos[vv]);
    	if(x==y) return;//已经双连通
    	if(find(uu)!=find(vv)){//未连通
    		link(x,y);
    		fa[fa[uu]]=fa[vv];
    	}
    	else{
    		makeroot(x);
    		access(y);splay(y);
    		y->val=y->sum;
    		dfs(y,y);
    	}
    }
    inline void change(tr *x,int k){
    	tr *findx=find(x);
    	splay(findx);
    	findx->val+=k;findx->sum+=k;
    }
    int main(){
    //		std::freopen("1.in","r",stdin);
    //		std::freopen("out","w",stdout);
    	int n=read(),m=read();
    	null=&dizhi[0];
    	null->setfa=null;
    	for(reg int i=1;i<=n;i++){
    		pos[i]=&dizhi[i];
    		dizhi[i].son[0]=dizhi[i].son[1]=dizhi[i].fa=null;
    		dizhi[i].sum=dizhi[i].val=val[i]=read();
    		dizhi[i].setfa=&dizhi[i];
    		fa[i]=i;
    	}
    	int uu,vv,op;
    	while(m--){
    		op=read();uu=read();vv=read();
    		if(op==1) Link(uu,vv);
    		else if(op==2) change(pos[uu],vv-val[uu]),val[uu]=vv;
    		else{
    			tr *x=find(pos[uu]),*y=find(pos[vv]);
    			if(find(uu)!=find(vv)) puts("-1");
    			else{
    				makeroot(x);
    				access(y);splay(y);
    				printf("%d
    ",y->sum);
    			}
    		} 
    	}
    	return 0;
    }
    
  • 相关阅读:
    PgSQL定时备份
    如何从源码包安装软件?
    PostgreSQL PointInTime Recovery (Incremental Backup)
    Better PostgreSQL backups with WAL archiving
    安装GTK全攻略
    WEB前端开发规范文档
    Linux开机自动启动脚本方法
    安装编译postgresql与pgagent的相关操作
    PostgreSQL: 如何查询表的创建时间?
    什么是编程
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/13475467.html
Copyright © 2020-2023  润新知