欢迎访问~原文出处——博客园-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; }