列表

详情


NC219171. 小Q与树

描述

小 Q 在纸上画树,画着画着,小 Q 在纸上画出了一棵  个点, 条边的树,其中他给第  个点都赋了一个点权 ,每条边的距离为

他想要知道


对  取模后的值。

输入描述

第一行一个整数 ,表示点的个数。               
接下来 个整数,其中第  个整数表示 。       
最后  行,每行两个整数 ,表示节点  与节点  之间有一条无向边。

输出描述

一行一个整数,表示答案。

示例1

输入:

5
3 2 4 6 5
1 2
2 3
2 4
4 5

输出:

112

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 544ms, 内存消耗: 33176K, 提交时间: 2021-06-04 16:16:11

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5+10;
const int mod = 998244353;
int n,a[maxn],ans;
vector<int>vec[maxn];
int siz[maxn],vis[maxn],mx[maxn],root,sumn;
typedef pair<int,int>p;
p res[maxn]; int top;
void getroot(int u,int fa)
{
	siz[u] = 1, mx[u] = 0;
	for( auto v:vec[u] )
	{
		if( vis[v] || v==fa )	continue;
		getroot(v,u);
		siz[u] += siz[v];
		mx[u] = max( mx[u],siz[v] );
	}
	mx[u] = max( mx[u],sumn-siz[u] );
	if( mx[u]<mx[root] )	root = u;
}
void dfs(int u,int fa,int dep)
{
	res[++top] = p( a[u],dep );
	for(auto v:vec[u] )
	{
		if( v==fa || vis[v] )	continue;
//		res[++top] = p( a[v],dep+1 );
		dfs( v,u,dep+1 );
	}
}
int calc(int u,int initdep)
{
	long long ans = 0, suf = 0;
	top = 0; dfs( u,u,initdep );
	sort( res+1,res+1+top );
	for(int i=top;i>=1;i--)
	{
//		ans = ( ans+min( res[i].first,a[u] )*res[i].second )%mod;
		ans = ( ans+1ll*res[i].first*(suf+1ll*res[i].second*(top-i)%mod)%mod )%mod;
		suf = ( suf+res[i].second )%mod;
	}
	return ans;
}
void solve(int u)
{
	vis[u] = 1; ans = ( ans+calc(u,0) )%mod;
	for(auto v:vec[u] )
	{
		if( vis[v] )	continue;
		ans = ( ans-calc(v,1) )%mod;
		sumn = siz[v], mx[root=0] = n+1;
		getroot(v,0); solve( root );
	}
}
int main()
{
	scanf("%d",&n );
	for(int i=1;i<=n;i++)	scanf("%d",&a[i] );
	for(int i=1;i<n;i++)
	{
		int l,r; scanf("%d%d",&l,&r);
		vec[l].push_back( r ); vec[r].push_back( l );
	}
	sumn = n, mx[root=0] = n+1;
	getroot(1,0); solve(1);
	printf("%d",(1ll*ans*2%mod+mod)%mod );
}

上一题