本題主要難點在於如何處理dist^2的問題c++
n^2暴力就沒必要多嘴,直接枚舉根節點DFS就好了。git
對於b=0的狀況,咱們能夠考慮用換根法來計算根節點的變化對總權值帶來的影響。
換根法通常的處理步驟是先以1爲根處理出一些信息,而後根據這些信息再作一次DFS。
那這道題要維護哪些信息呢?
考慮換根時都有哪些變了:假設根節點從u變到v,顯然,v及v的子樹的貢獻都會-dist(u,v)
,其餘節點的貢獻會+dist(u,v)。因此,總的權值變化就是dist(u,v)*(a[v子樹外的點]-a[子樹內的點])
隨便搞搞就好算法
對於b,咱們能夠如法炮製。對於一次換根(u->v):
對於v子樹的點:設原距離爲x,則貢獻從bx^2變爲b(x-dist(u,v))^2
兩式相減,可得變化量爲b(dist(u,v)^2-2xdist(u,v))。同理,子樹外的點的變化量爲b(dist(u,v)^2+2xdist(u,v))。
加到一塊兒,總變化量就是sumbdist(u,v)^2+2dist(u,v)(xb[v子樹外的點]-xb[子樹內的點])。
維護下必要的信息就好。spa
#include<bits/stdc++.h> using namespace std; #define re register ll #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) #define I inline void #define IN inline ll typedef long long ll; I read(ll &res){ re g=1;register char ch=getchar();res=0; while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } struct E{ int to,nt; }e[606000]; #define T e[k].to ll n,m,head[303000],S,ans,tot=-1,X,Y,suma,sumb,t[303000],siz[303000],a[303000],b[303000],f[303000],g[303000],A[303000],B[303000]; I D_1(ll x,ll fa){ A[x]=a[x];B[x]=b[x];f[x]=0;siz[x]=1;t[x]=0; for(re k=head[x];k!=-1;k=e[k].nt){ if(T==fa)continue; D_1(T,x);siz[x]+=siz[T]; A[x]+=A[T];B[x]+=B[T];f[x]+=f[T]+siz[T];t[x]+=(t[T]+B[T]); } } I D_2(ll x,ll fa,ll sum,ll dis){ g[x]=sum;S+=(a[x]*dis)+(b[x]*dis*dis); for(re k=head[x];k!=-1;k=e[k].nt){ if(T==fa)continue; D_2(T,x,sum+n-siz[T]-siz[T],dis+1); } } I D_3(ll x,ll fa,ll sum,ll num){ //cout<<"!"<<x<<" "<<sum<<" "<<num<<endl; ans=max(ans,sum); for(re k=head[x];k!=-1;k=e[k].nt){ if(T==fa)continue; D_3(T,x,sum+suma-A[T]-A[T]+sumb+2ll*(num+(t[x]-t[T]-B[T]))-2ll*(t[T]+B[T]),num+t[x]-t[T]-B[T]+sumb-B[T]); } } int main(){ //freopen("T1.in","r",stdin); //freopen("T1.out","w",stdout); read(n); memset(head,-1,sizeof(head)); suma=sumb=0; F(i,1,n){ read(a[i]);suma+=a[i]; } F(i,1,n){ read(b[i]);sumb+=b[i]; } F(i,1,n-1){ read(X);read(Y); e[++tot].to=Y; e[tot].nt=head[X]; head[X]=tot; e[++tot].to=X; e[tot].nt=head[Y]; head[Y]=tot; } D_1(1,0); S=0ll; D_2(1,0,f[1],0); D_3(1,0,S,0); //F(i,1,n){ //cout<<i<<":"<<f[i]<<" "<<g[i]<<" "<<A[i]<<" "<<B[i]<<" "<<t[i]<<endl; //} printf("%lld",ans); return 0; }