快一个月不更博了……打破沉寂的居然不是THUWC记这种水文,真是感动
这题的话答案等于sigma a[i]*i在的子串数量/总共的子串数量
即sigma a[i]*(l[i]*r[i]+len)/(n*(n+1)/2)
len是询问链的长度,l[i]和r[i]是在i这个点左右的点的个数
那么考虑LCT,然后对每条链维护sigma l[i]*r[i]*a[i],sigma l[i]*a[i],sigma r[i]*a[i],sigma a[i],siz,还有sigma l[i],sigma r[i],sigma l[i]*r[i]即可
具体的就自己YY一下然后看代码吧
LJSS说这是什么二次函数合并,并不知道他在说什么
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 50010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000000
#define INF 1000000007
int fa[MAXN],son[MAXN][2];
bool rev[MAXN];
int st[MAXN],tp;
ll siz[MAXN],sa[MAXN],sl[MAXN],sr[MAXN],slr[MAXN],slra[MAXN],sla[MAXN],sra[MAXN],ch[MAXN],a[MAXN];
int n,m;
ll gcd(ll x,ll y){
return !y?x:gcd(y,x%y);
}
inline void torev(int x){
if(!x){
return ;
}
swap(son[x][0],son[x][1]);
swap(sl[x],sr[x]);
swap(sla[x],sra[x]);
rev[x]^=1;
}
inline void toch(int x,ll y){
if(!x){
return ;
}
a[x]+=y;
ch[x]+=y;
slra[x]+=slr[x]*y;
sla[x]+=sl[x]*y;
sra[x]+=sr[x]*y;
sa[x]+=siz[x]*y;
}
inline void ud(int x){
slra[x]=slra[son[x][0]]+slra[son[x][1]]+
sla[son[x][0]]*(siz[son[x][1]]+1)+
sra[son[x][1]]*(siz[son[x][0]]+1)+
siz[son[x][0]]*siz[son[x][1]]*a[x]
;
sla[x]=sla[son[x][0]]+sla[son[x][1]]+(siz[son[x][0]]+1)*sa[son[x][1]]+siz[son[x][0]]*a[x];
sra[x]=sra[son[x][1]]+sra[son[x][0]]+(siz[son[x][1]]+1)*sa[son[x][0]]+siz[son[x][1]]*a[x];
sa[x]=sa[son[x][0]]+sa[son[x][1]]+a[x];
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
sl[x]=sl[son[x][0]]+sl[son[x][1]]+(siz[son[x][0]]+1)*siz[son[x][1]]+siz[son[x][0]];
sr[x]=sr[son[x][1]]+sr[son[x][0]]+(siz[son[x][1]]+1)*siz[son[x][0]]+siz[son[x][1]];
slr[x]=slr[son[x][0]]+slr[son[x][1]]+sl[son[x][0]]*(siz[son[x][1]]+1)+sr[son[x][1]]*(siz[son[x][0]]+1)+siz[son[x][0]]*siz[son[x][1]];
}
inline void pd(int x){
if(rev[x]){
torev(son[x][0]);
torev(son[x][1]);
rev[x]=0;
}
if(ch[x]){
toch(son[x][0],ch[x]);
toch(son[x][1],ch[x]);
ch[x]=0;
}
}
inline bool ir(int x){
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
inline void cot(int x,int y,bool z){
if(x){
fa[x]=y;
}
if(y){
son[y][z]=x;
}
}
inline void rot(int x,bool z){
int xx=fa[x],xxx=fa[xx];
cot(son[x][z],xx,z^1);
if(ir(xx)){
fa[x]=xxx;
}else{
cot(x,xxx,son[xxx][1]==xx);
}
cot(xx,x,z);
ud(xx);
}
inline void apd(int x){
int i;
st[++tp]=x;
for(i=x;!ir(i);i=fa[i]){
st[++tp]=fa[i];
}
for(;tp;tp--){
pd(st[tp]);
}
}
void splay(int x){
apd(x);
while(!ir(x)){
int xx=fa[x],xxx=fa[xx];
if(ir(xx)){
rot(x,son[xx][0]==x);
}else{
bool z=son[xxx][0]==xx;
if(son[xx][z]==x){
rot(x,z^1);
rot(x,z);
}else{
rot(xx,z);
rot(x,z);
}
}
}
ud(x);
}
inline void acs(int x){
int t=0;
while(x){
splay(x);
son[x][1]=t;
ud(x);
t=x;
x=fa[x];
}
}
inline void reboot(int x){
acs(x);
splay(x);
torev(x);
}
inline void link(int x,int y){
reboot(x);
fa[x]=y;
}
inline void cut(int x,int y){
reboot(x);
acs(y);
splay(y);
if(siz[y]==2){
son[y][0]=fa[x]=0;
ud(y);
}
}
int rt(int x){
acs(x);
splay(x);
pd(x);
while(son[x][0]){
x=son[x][0];
pd(x);
}
return x;
}
int main(){
int i,x,y,z,o;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
siz[i]=1;
ud(i);
}
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);
link(x,y);
}
while(m--){
scanf("%d",&o);
if(o==1){
scanf("%d%d",&x,&y);
cut(x,y);
}
if(o==2){
scanf("%d%d",&x,&y);
if(rt(x)!=rt(y)){
link(x,y);
}
}
if(o==3){
scanf("%d%d%d",&x,&y,&z);
if(rt(x)==rt(y)){
reboot(x);
acs(y);
splay(y);
toch(y,z);
}
}
if(o==4){
scanf("%d%d",&x,&y);
if(rt(x)==rt(y)){
reboot(x);
acs(y);
splay(y);
ll t=slra[y]+siz[y]*sa[y];
ll c=siz[y]*(siz[y]+1)/2;
ll g=gcd(t,c);
printf("%lld/%lld\n",t/g,c/g);
}else{
printf("-1\n");
}
}
}
return 0;
}
/*
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
*/