[BZOJ3091]城市旅行

[BZOJ3091] 城市旅行

Description

Input

Output

Sample Input

4 5
1 3 2 5
1 2
1 3
2 4
4 2 4
1 2 4
2 3 4
3 1 4 1
4 1 4

Sample Output

16/3
6/1

HINT

对于所有数据满足 \(1\leq N\leq 50,000 1\leq M\leq 50,000 1\leq Ai\leq 10^6 1\leq D\leq 100 1\leq U,V\leq N\)

试题分析

LCT一眼。
然后关键是维护信息:\(sz,sl,sr,sum,st,val\)分别表示Splay大小,权值与左边长度乘积的前缀和,权值与右边长度乘积的前缀和,子树和,答案,根节点权值。
那么更新如下:

inline void update(int x){
    sz[x]=sz[lc]+sz[rc]+1;
    sum[x]=sum[lc]+sum[rc]+val[x];
    sl[x]=sl[lc]+sl[rc]+(sz[lc]+1)*(val[x]+sum[rc]); //左边的前缀和+右边的前缀和+左边让右边向右移的那些位乘上右边的子树和,这里是展开形式
    sr[x]=sr[rc]+sr[lc]+(sz[rc]+1)*(val[x]+sum[lc]);//同上
    st[x]=st[lc]+st[rc]+(sz[lc]+1)*sl[rc]+(sz[rc]+1)*sr[lc]+val[x]*(sz[lc]+1)*(sz[rc]+1);//根节点的权值,两边信息与两边在根节点处合并
}

注意常数和细节就没了。。。 为什么数据那么水,暴力水了rk1

  • 注意一下交换左右儿子的时候sl和sr也要交换
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<algorithm>

using namespace std;
#define LL long long

inline int read(){
	int x=0,f=1; char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0';
	return x*f;
}
const int INF = 2147483600;
const int MAXN = 50010;

int N,M; LL val[MAXN+1];
int ch[MAXN+1][2],fa[MAXN+1];
int dep[MAXN+1]; bool col[MAXN+1];
LL tag_val[MAXN+1];
LL sz[MAXN+1]; LL sum[MAXN+1];
LL sl[MAXN+1],sr[MAXN+1],st[MAXN+1];

inline void Union(int son,int f,int x){ch[f][x]=son; fa[son]=f;}
inline int chd(int x){return ch[fa[x]][0]==x?0:1;}
inline bool nroot(int x){return (ch[fa[x]][0]==x)|(ch[fa[x]][1]==x);}

inline void Colorf(int x){swap(ch[x][0],ch[x][1]); swap(sl[x],sr[x]); col[x]^=1; return ;}
inline void Add_val(int x,LL a){
	val[x]+=a; tag_val[x]+=a; 
	sum[x]+=sz[x]*a; sl[x]+=sz[x]*(sz[x]+1)/2*a;
	sr[x]+=sz[x]*(sz[x]+1)/2*a; st[x]+=(sz[x]+2)*(sz[x]+1)*sz[x]/6*a;
	return ;
}
inline void pushdown(int x){
	if(col[x]){Colorf(ch[x][0]); Colorf(ch[x][1]); col[x]=0;}
	if(tag_val[x]){Add_val(ch[x][0],tag_val[x]); Add_val(ch[x][1],tag_val[x]); tag_val[x]=0;}
}
inline void update(int x){
	sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x];
	sl[x]=sl[ch[x][0]]+(sz[ch[x][0]]+1)*(sum[ch[x][1]]+val[x])+sl[ch[x][1]];
	sr[x]=sr[ch[x][1]]+(sz[ch[x][1]]+1)*(sum[ch[x][0]]+val[x])+sr[ch[x][0]];
	st[x]=st[ch[x][0]]+st[ch[x][1]]+sl[ch[x][0]]*(sz[ch[x][1]]+1)+sr[ch[x][1]]*(sz[ch[x][0]]+1)+val[x]*(sz[ch[x][0]]+1)*(sz[ch[x][1]]+1);
	return ;
}
inline void rotate(int x){
	int y=fa[x],z=fa[y];
    int k=ch[y][1]==x,w=ch[x][k^1];
    if(nroot(y)) ch[z][ch[z][1]==y]=x;
    ch[y][k]=w;ch[x][k^1]=y;
    fa[x]=z;fa[y]=x; if(w) fa[w]=y; update(y); update(x);
}
inline void pushup(int x){
	if(nroot(x)) pushup(fa[x]);
	pushdown(x);
}
inline void Splay(int x){
    int y=x; pushup(x);
    while(nroot(x)){
        y=fa[x]; if(nroot(y)) rotate((chd(x)==0)^(chd(y)==0)?x:y);
        rotate(x);
    } return ;
}
inline void access(int x){
	for(int y=0;x;y=x,x=fa[x]) {
		Splay(x); ch[x][1]=y; update(x);
	} return ;
}
inline void chroot(int x){access(x); Splay(x); Colorf(x);}
inline int findroot(int x){ while(fa[x]) x=fa[x]; return x;}
inline void split(int x,int y){chroot(x); access(y); Splay(y); return ;}
inline void link(int x,int y){
	if(findroot(x)!=findroot(y)) chroot(x),fa[x]=y;
}
inline void cut(int x,int y){
    split(x,y); if(fa[x]==y){
		fa[x]=ch[y][0]=0; update(y);
	}return ;
}
inline void Add(int x,int y,LL d){
	split(x,y); Add_val(y,d); return ;
}
inline LL gcd(LL a,LL b){
	if(!b) return a;
	return gcd(b,a%b);
}

int main(){
	N=read(),M=read();
	for(int i=1;i<=N;i++) val[i]=read(),update(i);
	for(int i=2;i<=N;i++){
		int u=read(),v=read();
		link(u,v);
	} for(int i=1;i<=M;i++){
		int opr=read();
		if(opr==1){
			int u=read(),v=read(); cut(u,v);
		} else if(opr==2){
			int u=read(),v=read(); link(u,v);
		} else if(opr==3){
			int u=read(),v=read(),d=read(); 
			if(findroot(u)==findroot(v)) Add(u,v,d);
		} else if(opr==4){
			int x=read(),y=read(); 
			if(findroot(x)==findroot(y)){
				split(x,y); LL z=st[y],d=(sz[y]*(sz[y]+1))>>1;
				LL dt=gcd(z,d); printf("%lld/%lld\n",z/dt,d/dt);
			} else puts("-1");
		}
	}
	return 0;
}
posted @ 2018-08-10 17:02  wxjor  阅读(125)  评论(0编辑  收藏  举报