题解 【SR3-T3】【船往低处流】
\small\textbf{Subtask 1}
直接根据题目当中的式子进行计算。
当然了,如果你采用了「枚举子树」后「分别枚举
\small\textbf{Subtask 2}
这个
为了方便起见,记
考虑计算
运用换根
那么
感性理解一下,就是对子树的
那么就能计算出,
假设已经计算出了
然后就能计算出
容易发现这样子计算一棵子树的时间复杂度为
\small\textbf{Subtask 3,4}
大概有特殊规律吧,我没找过。
\small\textbf{Subtask 5}
考虑如何计算大小为
同
为了方便计算,我们可以去除
此外,我们还定义:
为了方便计算,我们还要定义另外一个东西
一种比较常见的树形
现在假设要处理根为
下面不妨记蓝色区域为区域
\mathbf{LCAS_0}
- 第一种情况:根节点
i 在A 当中。 -
- 第二种情况:根节点
i 在B 当中。其实这种情况和第一种情况类似,可以如法炮制。 -
通过上述讨论,我们可以得到新的
初始时
\mathbf{LCAS_1}
这部分问题相对而言比较简单。
- 第一种情况,
j,k 在A 当中。容易发现这部分贡献就是\mathrm{LCAS}_1(u) 。 - 第二种情况,
j,k 在B 当中。容易发现这部分贡献就是\mathrm{LCAS}_1(v) 。 - 第三种情况,
j 在A 当中,k 在B 当中。此时\mathrm{lca}(u,j,k) 必然是u ,因此容易得到贡献就是w_u\cdot\mathit{siz}(j)\cdot \mathit{siz}(k) 。 - 第四种情况,
j 在B 当中,k 在A 当中。同上,贡献是w_u\cdot\mathit{siz}(j)\cdot \mathit{siz}(k) 。
因此,
初始时
\mathbf{LCAS_2}
这部分问题也不太难。
- 第一种情况,
i,k 都在A 当中。容易发现可以根据定义得到该部分的贡献是\mathrm{LCAS_2}(u) 。 - 第一种情况,
i,k 都在B 当中。此时可以发现,u 的地位和v 的地位等同,也就是说,\sum_{i\in B}\sum_{k\in B} w_{\mathrm{lca}(i,u,k)}=\sum_{i\in B}\sum_{k\in B} w_{\mathrm{lca}(i,v,k)} 因此贡献是
\mathrm{LCAS_2}(v) 。 - 第三种情况,
i 在A 当中,k 在B 当中。此时可以发现\mathrm{lca}(i,u,k)=u ,因此贡献是w_u\cdot \mathit{siz}(u)\cdot \mathit{siz}(v) 。 - 第四种情况,
i 在B 当中,k 在A 当中。此时可以发现\mathrm{lca}(i,u,k)=u ,因此贡献是w_u\cdot \mathit{siz}(u)\cdot \mathit{siz}(v) 。
因此,
初始时
总结
容易发现,
记得最后把
参考代码
\small \textbf{Subtask 1}
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
const int MAXN=100+3;
int n,W[MAXN];
int qread(){
int w=1,c,ret;
while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*w;
}
int H[MAXN],V[MAXN*2],N[MAXN*2],G[MAXN],t;
void add(int u,int v){
V[++t]=v,N[t]=H[u],H[u]=t;
}
int L[MAXN][MAXN][MAXN],F[MAXN]; bool T[MAXN];
int A[MAXN],B[MAXN],S[MAXN],s;
void dfs(int u,int f){
S[++s]=u,A[u]=s;
for(int i=H[u],v;i;i=N[i]) if((v=V[i])!=f) dfs(v,u);
B[u]=s;
}
const int MOD =998244353;
int main(){
n=qread(); up(1,n,i) W[i]=qread();
up(1,n-1,i){
int u=qread(),v=qread(); add(u,v),add(v,u);
}
up(1,n,r){
memset(F,0,sizeof(F)); F[r]=r; queue <int> Q; Q.push(r);
while(!Q.empty()){
int u=Q.front(); Q.pop();
for(int i=H[u],v;i;i=N[i]) if(!F[v=V[i]]){
F[v]=u,Q.push(v);
}
}
up(1,n,i) up(1,n,j){
int u=i,v=j; memset(T,0,sizeof(T));
while(u!=r) T[u]=true,u=F[u]; T[r]=true;
while(v!=r) if(T[v]){
L[r][i][j]=v; goto nxt;
} else v=F[v];
L[r][i][j]=r; nxt:;
}
}
dfs(1,0); up(1,n,r){
int w=0,a=A[r],b=B[r];
up(a,b,i) up(a,b,j) up(a,b,k) if(S[j]<S[k])
w=(w+W[L[S[i]][S[j]][S[k]]])%MOD;
printf("%d\n",w);
}
return 0;
}
\small \textbf{Subtask 2}
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
const int MAXN=1000+3;
int qread(){
int w=1,c,ret;
while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*w;
}
int n,H[MAXN],V[MAXN*2],N[MAXN*2],t;
void add(int u,int v){
V[++t]=v,N[t]=H[u],H[u]=t;
}
const int MOD =998244353;
int S[MAXN],W[MAXN],X[MAXN],F[MAXN];
void dfs0(int u,int f){
F[u]=f;
for(int i=H[u],v;i;i=N[i]) if((v=V[i])!=f) dfs0(v,u);
}
void dfs1(int u,int f){
for(int i=H[u],v;i;i=N[i]) if((v=V[i])!=f){
dfs1(v,u);
X[u]=(1ll*W[u]*S[v]%MOD*S[u]+X[v]+X[u])%MOD,S[u]+=S[v];
}
X[u]=(1ll*W[u]*S[u]+X[u])%MOD,++S[u];
}
int r;
void dfs2(int u,int f){
r=(r+X[u])%MOD;
for(int i=H[u],v;i;i=N[i]) if((v=V[i])!=f){
X[v]=((-1ll*(W[u]-W[v]+MOD)*(S[u]-S[v]+MOD)%MOD
*S[v]+X[u])%MOD+MOD)%MOD;
S[v]=S[u],dfs2(v,u);
}
}
int main(){
n=qread(); up(1,n,i) W[i]=qread();
up(1,n-1,i){
int u=qread(),v=qread(); add(u,v),add(v,u);
}
dfs0(1,0);
up(1,n,i){
memset(S,0,sizeof(S));
memset(X,0,sizeof(X));
dfs1(i,F[i]),dfs2(i,F[i]);
printf("%d\n",r),r=0;
}
return 0;
}
\small \textbf{Subtask 5}
#include<bits/stdc++.h>
#define up(l,r,i) for(int i=l,END##i=r;i<=END##i;++i)
#define dn(r,l,i) for(int i=r,END##i=l;i>=END##i;--i)
using namespace std;
typedef long long i64;
const int INF =2147483647;
const int MAXN=1e6+3,MAXM=MAXN*2;
const int MOD =998244353,DIV2=499122177;
int n,A[MAXN],S0[MAXN],S1[MAXN],W[MAXN],T[MAXN];
namespace Gra{
int H[MAXN],V[MAXM],N[MAXM],S[MAXN],t;
void add(int u,int v){V[++t]=v,N[t]=H[u],H[u]=t;}
void dfs(int u,int f){
S0[u]=S1[u]=T[u]=W[u],S[u]=1;
for(int i=H[u],v;i;i=N[i]) if((v=V[i])!=f){
dfs(v,u); int s0=0,s1=0;
s0=(1ll*S0[u]+3ll*S[v]*S1[u]%MOD
+1ll*S0[v]+3ll*S[u]*S1[v]%MOD)%MOD;
s1=(1ll*S1[u]+S1[v]+2ll*W[u]*S[u]%MOD*S[v]%MOD)%MOD;
S0[u]=s0,S1[u]=s1,S[u]+=S[v],T[u]=(T[u]+T[v])%MOD;
}
A[u]=1ll*(1ll*S0[u]-1ll*S[u]*T[u]%MOD+MOD)*DIV2%MOD;
}
}
int qread(){
int w=1,c,ret;
while((c=getchar())> '9'||c< '0') w=(c=='-'?-1:1); ret=c-'0';
while((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*w;
}
int main(){
n=qread(); up(1,n,i) W[i]=qread();
up(1,n-1,i){
int u=qread(),v=qread(); Gra::add(u,v),Gra::add(v,u);
}
Gra::dfs(1,0);
up(1,n,i) printf("%d\n",A[i]);
return 0;
}