版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/86663378
orz SongHL https://www.cnblogs.com/songorz/p/9912208.html
上课讲的例题,讲得比qt清楚多了,lct也讲的很透,很好理解
#include<bits/stdc++.h>
#define maxl 50010
#define LL long long
using namespace std;
const int inf=0x3f3f3f3f;
int n,m;
int fa[maxl];
struct node
{
int son[2];
long long sum,tag,rev,ans,val,lsum,rsum,size;
int& operator [] (int x) {return son[x];}
}tree[maxl];
long long gcd(long long a,long long b)
{
if(b==0)
return a;
else
return gcd(b,a%b);
}
namespace LCT
{
void reverse(int k)
{
swap(tree[k][0],tree[k][1]);
swap(tree[k].lsum,tree[k].rsum);
tree[k].rev^=1;
}
void add(int k,LL val)
{
tree[k].val+=val;
tree[k].sum+=tree[k].size*val;
tree[k].tag+=val;
tree[k].ans+=tree[k].size*(tree[k].size+1)*(tree[k].size+2)/6*val;
tree[k].lsum+=tree[k].size*(tree[k].size+1)/2*val;
tree[k].rsum+=tree[k].size*(tree[k].size+1)/2*val;
}
int find(int x) {return fa[x] ? find(fa[x]):x;}
void pushdown(int k)
{
if(tree[fa[k]][0]==k || tree[fa[k]][1]==k) pushdown(fa[k]);
int l=tree[k][0],r=tree[k][1];
if(tree[k].rev)
{
if(l) reverse(l);
if(r) reverse(r);
tree[k].rev^=1;
}
if(tree[k].tag)
{
if(l) add(l,tree[k].tag);
if(r) add(r,tree[k].tag);
tree[k].tag=0;
}
}
void pushup(int k)
{
int l=tree[k][0],r=tree[k][1];
tree[k].size=tree[l].size+tree[r].size+1;
tree[k].lsum=tree[l].lsum+(tree[l].size+1)*tree[k].val+tree[r].lsum+tree[r].sum*(tree[l].size+1);
tree[k].rsum=tree[r].rsum+(tree[r].size+1)*tree[k].val+tree[l].rsum+tree[l].sum*(tree[r].size+1);
tree[k].sum=tree[l].sum+tree[r].sum+tree[k].val;
tree[k].ans=tree[l].ans+tree[r].ans+tree[l].lsum*(tree[r].size+1)+tree[r].rsum*(tree[l].size+1)+tree[k].val*(tree[l].size+1)*(tree[r].size+1);
}
void rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
l=(tree[y][1]==x);r=l^1;
if(tree[z][0]==y || tree[z][1]==y)
tree[z][tree[z][1]==y]=x;
fa[tree[x][r]]=y;fa[x]=z;fa[y]=x;
tree[y][l]=tree[x][r];tree[x][r]=y;
pushup(y);pushup(x);
}
void splay(int x)
{
pushdown(x);
while(tree[fa[x]][0]==x || tree[fa[x]][1]==x)
{
int y=fa[x],z=fa[y];
if(tree[z][0]==y || tree[z][1]==y)
{
if(tree[z][0]==y ^ tree[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),tree[x][1]=y,pushup(x);
}
int findroot(int x)
{
access(x),splay(x);
while(tree[x][0]) pushdown(x),x=tree[x][0];
return x;
}
void makeroot(int x)
{
access(x);splay(x);reverse(x);
}
void split(int x,int y)
{
makeroot(x);
access(y);splay(y);
}
void link(int x,int y)
{
makeroot(x);fa[x]=y;
}
void cut(int x,int y)
{
makeroot(x);access(y);splay(y);
if(tree[y][0]==x && tree[x][1]==0)
tree[y][0]=0,fa[x]=0,pushup(y);
}
void modify(int x,int y,long long val)
{
makeroot(x);access(y);
splay(y);add(y,val);
}
void query(int x,int y)
{
split(x,y);
long long A=tree[y].ans;
long long B=tree[y].size*(tree[y].size+1)/2;
long long D=gcd(A,B);
printf("%lld/%lld\n",A/D,B/D);
}
}
using namespace LCT;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&tree[i].val);
int u,v;
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
link(u,v);
}
int opt,x,y,d;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&opt,&x,&y);
if(opt==1)
if(find(x)==find(y))
cut(x,y);
if(opt==2)
if(find(x)!=find(y))
link(x,y);
if(opt==3)
{
scanf("%d",&d);
if(find(x)==find(y))
modify(x,y,d);
}
if(opt==4)
if(find(x)==find(y))
query(x,y);
else
puts("-1");
}
return 0;
}