• 【bzoj3091】 城市旅行


    http://www.lydsy.com/JudgeOnline/problem.php?id=3091 (题目链接)

    题意

      给出一棵无根树,维护四个操作。link,cut,路径加法,路径期望查询。

    Solution

      右转题解→_→:PoPoQQQ

      对于无法直接维护的值,我们可以考虑做差,或者是用别的比较好维护的值来加减乘除得到。

    细节

      全程LL,先翻转再打标记。

    代码

    // bzoj3091
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<map>
    #define LL long long
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    
    const int maxn=50010;
    int n,m,fa[maxn];
    struct node {
    	int son[2];
    	LL sum,tag,rev,ans,val,lsum,rsum,size;
    	int& operator [] (int x) {return son[x];}
    }tr[maxn];
    
    LL gcd(LL a,LL b) {return b==0 ? a : gcd(b,a%b);}
    namespace LCT {
    	void reverse(int k) {
    		swap(tr[k][0],tr[k][1]);
    		swap(tr[k].lsum,tr[k].rsum);
    		tr[k].rev^=1;
    	}
    	void add(int k,LL val) {
    		tr[k].val+=val;
    		tr[k].sum+=tr[k].size*val;
    		tr[k].tag+=val;
    		tr[k].ans+=tr[k].size*(tr[k].size+1)*(tr[k].size+2)/6*val;
    		tr[k].lsum+=tr[k].size*(tr[k].size+1)/2*val;
    		tr[k].rsum+=tr[k].size*(tr[k].size+1)/2*val;
    	}
    	void pushdown(int k) {
    		if (tr[fa[k]][0]==k || tr[fa[k]][1]==k) pushdown(fa[k]);
    		int l=tr[k][0],r=tr[k][1];
    		if (tr[k].rev) {
    			if (l) reverse(l);
    			if (r) reverse(r);
    			tr[k].rev^=1;
    		}
    		if (tr[k].tag) {
    			if (l) add(l,tr[k].tag);
    			if (r) add(r,tr[k].tag);
    			tr[k].tag=0;
    		}
    	}
    	void pushup(int k) {
    		int l=tr[k][0],r=tr[k][1];
    		tr[k].size=tr[l].size+tr[r].size+1;
    		tr[k].lsum=tr[l].lsum+(tr[l].size+1)*tr[k].val+tr[r].lsum+tr[r].sum*(tr[l].size+1);
    		tr[k].rsum=tr[r].rsum+(tr[r].size+1)*tr[k].val+tr[l].rsum+tr[l].sum*(tr[r].size+1);
    		tr[k].sum=tr[l].sum+tr[r].sum+tr[k].val;
    		tr[k].ans=tr[l].ans+tr[r].ans+tr[l].lsum*(tr[r].size+1)+tr[r].rsum*(tr[l].size+1)+tr[k].val*(tr[l].size+1)*(tr[r].size+1);
    	}
    	void rotate(int x) {
    		int y=fa[x],z=fa[y],l,r;
    		l=tr[y][1]==x;r=l^1;
    		if (tr[z][0]==y || tr[z][1]==y) tr[z][tr[z][1]==y]=x;
    		fa[tr[x][r]]=y;fa[x]=z;fa[y]=x;
    		tr[y][l]=tr[x][r];tr[x][r]=y;
    		pushup(y);pushup(x);
    	}
    	void splay(int x) {
    		pushdown(x);
    		while (tr[fa[x]][0]==x || tr[fa[x]][1]==x) {
    			int y=fa[x],z=fa[y];
    			if (tr[z][0]==y || tr[z][1]==y) {
    				if (tr[z][0]==y ^ tr[y][0]==x) rotate(x);
    				else rotate(y);
    			}
    			rotate(x);
    		}
    	}
    	void access(int x) {
    		for (int y=0;x;y=x,x=fa[x]) splay(x),tr[x][1]=y,pushup(x);
    	}
    	void makeroot(int x) {
    		access(x);splay(x);reverse(x);
    	}
    	void link(int x,int y) {
    		makeroot(x);fa[x]=y;
    	}
    	void cut(int x,int y) {
    		makeroot(x);access(y);splay(y);
    		if (tr[y][0]==x && tr[x][1]==0)
    			tr[y][0]=0,fa[x]=0,pushup(y);
    	}
    	void modify(int x,int y,LL val) {
    		makeroot(x);access(y);splay(y);add(y,val);
    	}
    	int find(int x) {
    		return fa[x] ? find(fa[x]) : x;
    	}
    	void query(int x,int y) {
    		makeroot(x);access(y);splay(y);
    		LL A=tr[y].ans,B=tr[y].size*(tr[y].size+1)/2;
    		LL D=gcd(A,B);
    		printf("%lld/%lld
    ",A/D,B/D);
    	}
    }
    using namespace LCT;
    
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) scanf("%lld",&tr[i].val);
    	for (int u,v,i=1;i<n;i++) {
    		scanf("%d%d",&u,&v);
    		link(u,v);
    	}
    	for (int op,x,y,d,i=1;i<=m;i++) {
    		scanf("%d%d%d",&op,&x,&y);
    		if (op==1) if (find(x)==find(y)) cut(x,y);
    		if (op==2) if (find(x)!=find(y)) link(x,y);
    		if (op==3) {scanf("%d",&d);if (find(x)==find(y)) modify(x,y,d);}
    		if (op==4) if (find(x)==find(y)) query(x,y);else puts("-1");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Struts2中validate数据校验的两种常用方法
    Oracle中主键、外键、索引、序列、唯一性约束的创建
    Hibernate学习(五)Hibernate 多对多映射
    oracle实现主键自增
    现代软件工程 第三章:【软件工程师的成长】练习与讨论
    现代软件工程 第十七章 【人、绩效和职业道德】 练习与讨论
    现代软件工程 第十章 【典型用户和场景】 练习与讨论
    现代软件工程 第八章 【需求分析】练习与讨论
    现代软件工程 第七章 【MSF】练习与讨论
    现代软件工程 第六章 【敏捷流程】练习与讨论
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6479163.html
Copyright © 2020-2023  润新知