• BZOJ3091 城市旅行 LCT


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ3091


    题意概括

      鉴于本人语文不好,此题的描述原题很清晰,废话不多,请看原题。

      可怕,原题是图片,不可以复制题目+删掉废话了……


    题解

      http://blog.csdn.net/popoqqq/article/details/40823659

      这位大佬写的很好。

      我的代码在找错的时候一边找,一边该,然后发现和他改的好像……


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    typedef long long LL;
    const int N=50005;
    struct Gragh{
    	int cnt,y[N*2],nxt[N*2],fst[N];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int n,m;
    int fa[N],son[N][2],rev[N];
    LL size[N],val[N],add[N],sum[N],Lsum[N],Rsum[N],Exp[N];
    bool isroot(int x){
    	return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
    }
    void pushup(int x){
    	int ls=son[x][0],rs=son[x][1],lsz=size[ls],rsz=size[rs];
    	size[x]=lsz+rsz+1;
    	sum[x]=sum[ls]+sum[rs]+val[x];
    	Lsum[x]=Lsum[ls]+(lsz+1)*val[x]+Lsum[rs]+sum[rs]*(lsz+1);
    	Rsum[x]=Rsum[rs]+(rsz+1)*val[x]+Rsum[ls]+sum[ls]*(rsz+1);
    	Exp[x]=Exp[ls]+Exp[rs]+Lsum[ls]*(rsz+1)+Rsum[rs]*(lsz+1)+val[x]*(lsz+1)*(rsz+1);
    }
    void pushson(int x,LL v){
    	if (!x)
    		return;
    	val[x]+=v,sum[x]+=v*size[x],add[x]+=v;
    	Lsum[x]+=v*size[x]*(size[x]+1)/2;
    	Rsum[x]+=v*size[x]*(size[x]+1)/2;
    	Exp[x]+=v*size[x]*(size[x]+1)*(size[x]+2)/6;
    }
    void pushrev(int x){
    	rev[x]^=1;
    	swap(son[x][0],son[x][1]);
    	swap(Lsum[x],Rsum[x]);
    }
    void pushdown(int x){
    	int &ls=son[x][0],&rs=son[x][1];
    	if (rev[x]){
    		rev[x]=0;
    		pushrev(ls);
    		pushrev(rs);
    	}
    	if (add[x]){
    		LL &a=add[x];
    		pushson(ls,a);
    		pushson(rs,a);
    		a=0;
    	}
    }
    void pushadd(int x){
    	if (!isroot(x))
    		pushadd(fa[x]);
    	pushdown(x);
    }
    int wson(int x){
    	return son[fa[x]][1]==x;
    }
    void rotate(int x){
    	if (isroot(x))
    		return;
    	int y=fa[x],z=fa[y],L=wson(x),R=L^1;
    	if (!isroot(y))
    		son[z][wson(y)]=x;
    	fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
    	son[y][L]=son[x][R],son[x][R]=y;
    	pushup(y),pushup(x);
    }
    void splay(int x){
    	pushadd(x);
    	for (int y=fa[x];!isroot(x);rotate(x),y=fa[x])
    		if (!isroot(y))
    			rotate(wson(x)==wson(y)?y:x);
    }
    void access(int x){
    	int t=0;
    	while (x){
    		splay(x);
    		son[x][1]=t;
    		pushup(x);
    		t=x;
    		x=fa[x];
    	}
    }
    void rever(int x){
    	access(x);
    	splay(x);
    	pushrev(x);
    }
    void link(int x,int y){
    	rever(x);
    	fa[x]=y;
    }
    void cut(int x,int y){
    	rever(x);
    	access(y);
    	splay(y);
    	fa[x]=son[y][0]=0;
    }
    int find(int x){
    	access(x);
    	splay(x);
    	while (1){
    		pushdown(x);
    		if (son[x][0])
    			x=son[x][0];
    		else
    			break;
    	}
    	return x;
    }
    void dfs(int x,int pre){
    	fa[x]=pre;
    	for (int i=g.fst[x];i;i=g.nxt[i])
    		if (g.y[i]!=pre)
    			dfs(g.y[i],x);
    }
    LL gcd(LL a,LL b){
    	return b==0?a:gcd(b,a%b);
    }
    void solve(int x,int y){
    	if (find(x)!=find(y)){
    		puts("-1");
    		return;
    	}
    	rever(x);
    	access(y);
    	splay(y);
    	LL a=Exp[y];
    	LL b=size[y]*(size[y]+1)/2;
    	LL Gcd=gcd(a,b);
    	a/=Gcd,b/=Gcd;
    	printf("%lld/%lld
    ",a,b);
    }
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++){
    		scanf("%lld",&val[i]);
    		fa[i]=son[i][0]=son[i][1]=rev[i]=0;
    		size[i]=1,Exp[i]=Lsum[i]=Rsum[i]=sum[i]=val[i],add[i]=0;
    	}
    	g.clear();
    	for (int i=1,a,b;i<n;i++){
    		scanf("%d%d",&a,&b);
    		g.add(a,b),g.add(b,a);
    	}
    	dfs(1,0);
    	for (int i=1;i<=m;i++){
    		int op,x,y;
    		LL v;
    		scanf("%d%d%d",&op,&x,&y);
    		if (op==1){
    			if (find(x)==find(y))
    				cut(x,y);
    		}
    		else if (op==2){
    			if (find(x)!=find(y))
    				link(x,y);
    		}
    		else if (op==3){
    			scanf("%lld",&v);
    			if (find(x)!=find(y))
    				continue;
    			rever(x);
    			access(y);
    			splay(y);
    			pushson(y,v);
    		}
    		else
    			solve(x,y);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    我的.emacs配置文件
    C语言夜未眠5——变量前缀代表的含义
    c语言夜未眠4——对某一位或几位进行反转
    指针也可这么玩:返回局部指针变量,局部噢
    lua学习之table类型
    10个最“优秀”的代码注释
    为什么我希望用C而不是C++来实现ZeroMQ
    c语言夜未眠2——实现撤销和重做
    emacs学习笔记(基本概念)
    flutter json_serializable
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3091.html
Copyright © 2020-2023  润新知