首页 > 其他分享 >题解 P9437『XYGOI round1』一棵树

题解 P9437『XYGOI round1』一棵树

时间:2023-07-17 23:12:34浏览次数:43  
标签:10 P9437 题解 sum int XYGOI siz cdot ll

换根 DP。

本蒟蒻最初没想到换根,把自己写自闭了...

定义 \(f_u\) 为子树 \(u\) 中的每个结点走到 \(u\) 的贡献和,\(l_u\) 为大于 \(a_u\) 的最小的 \(10\) 的幂次方数,\(sum_u\) 为 \(\sum\limits_{v\in son(u)}{f_v}\)。

转移方程为:\(f_u=l_u\cdot\sum\limits_{v\in son(u)}{f_v}+siz_u\cdot a_u\)。

再定义 \(g_u\) 为除去子树 \(u\) 其他的所有点到 \(fa_u\) 的贡献和。

转移方程为:\(g_v=(g_u+sum_u-f_v)\cdot l_u+(n-siz_v)\cdot a_u\)。

然后答案加上 \((g_v+sum_v)\cdot l_v+n\cdot a_v\)。

复杂度 \(O(n)\)。

code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5,mod=998244353;
ll n,a[N],f[N],g[N],siz[N],sum[N],ans;
vector<int>adj[N];
ll get(ll x){
	if(x==0)return 10;
	ll res=1;
	while(x){res*=10;x/=10;}
	return res;
}
void dfs(int u,int lst){
	siz[u]=1;
	ll t=get(a[u]);f[u]=a[u];
	for(int i=0;i<adj[u].size();++i){
		int v=adj[u][i];if(v==lst)continue;
		dfs(v,u);siz[u]+=siz[v];f[u]=(f[u]+f[v]*t+siz[v]*a[u])%mod;sum[u]=(sum[u]+f[v])%mod;
	}
}
void dfs2(int u,int lst){
	ll tu=get(a[u]);
	for(int i=0;i<adj[u].size();++i){
		ll v=adj[u][i],tv=get(a[v]);if(v==lst)continue;
		g[v]=(g[u]+(sum[u]-f[v]+mod)%mod)%mod*tu+(n-siz[v])*a[u];g[v]%=mod;
		ans=(ans+(g[v]+sum[v])*tv+n*a[v])%mod;
		dfs2(v,u);
	}
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n;for(int i=1;i<=n;++i)cin>>a[i];
	for(int u=2;u<=n;++u){
		int v;cin>>v;
		adj[u].push_back(v);adj[v].push_back(u);
	}
	dfs(1,0);ans+=f[1];dfs2(1,0);
	cout<<ans<<endl;
	return 0;
}

标签:10,P9437,题解,sum,int,XYGOI,siz,cdot,ll
From: https://www.cnblogs.com/HQJ2007/p/17561568.html

相关文章

  • 决策单调性优化DP 学习笔记 & P4767 [IOI2000] 邮局 题解
    0.题面题目描述高速公路旁边有一些村庄。高速公路表示为整数轴,每个村庄的位置用单个整数坐标标识。没有两个在同样地方的村庄。两个位置之间的距离是其整数坐标差的绝对值。邮局将建在一些,但不一定是所有的村庄中。为了建立邮局,应选择他们建造的位置,使每个村庄与其最近的邮局......
  • 题解 P7215
    点分治。考虑当前的分治重心的城市被完全联通。这可以用队列接解决。每次放入一种城市,就把那些城镇的父亲加入队列,如果存在城镇不在当前分治重心的联通块内,那么说明必定存在另一个分治重心能算到它,直接退出即可。剩下的和模板没有任何区别。复杂度\(O(n\logn)\)。code:#in......
  • 题解 P6329
    点分树模板题。是个神奇的算法。点分树就是将分治重心按照层级连边,每个节点父亲的联通块都包含了当前节点的联通块,且高度为\(\logn\)。可以解决不考虑树的形态的多次询问带修改的问题。对于这道题,我们可以在点分树的每个节点上记录两棵树状数组,分别与当前节点距离为\(k\)的......
  • 题解 P3345
    点分树。本题的核心问题在于不好直接确定补给站的位置。但是仔细思考后我们发现,对于当前节点,如果存在一个儿子的答案比它优,那么补给站一定在那个儿子的子树中。增量为\(w\times(sum_u-2\cdotsum_v)\)。当\(v\)优于\(u\)时,\(2\cdotsum_v>sum_u\)。如果\(v_2\)也满足,则......
  • 题解 P5384
    这题有紫??对于询问节点\(u\),倍增地跳到它的\(k\)级祖先,求其子树内有多少深度为\(dep_u\)的节点。我们考虑把询问离线,再通过dfs序把树拍平,然后扫一遍直接求就行了。复杂度\(O(n\logn)\)。code:#include<bits/stdc++.h>usingnamespacestd;constintN=1e6+5;inlin......
  • 题解 P3806
    点分治模板题。点分治适合处理大规模的树上路径信息问题暴力做法:dfs每个点\(u\),算出其子树内每个点到\(u\)的距离,统计经过\(u\)的所有路径,复杂度\(O(n^2)\)。容易发现,复杂度和子树大小有关。对于当前子树,我们可以求出其重心,计算经过重心的所有路径,删掉重心,递归每个联通......
  • 题解 CF1271D
    贪心+DP。对于一个点,后选显然比先选好,也就是说每个点都对应了唯一一个来源。于是我们可以把每个点所能回溯到的点的收益值从大到小排序,贪心地选前缀。定义\(f_{i,j}\)表示考虑了前\(i\)个点,剩下\(j\)个人,最大收益。转移方程和\(01\)背包的一样。\[f_{i,j}=f_{i-1,j-b......
  • 题解 CF213C
    考虑朴素DP。定义\(f_{i,j,i2,j2}\)表示两个人分别在\((i,j),(i2,j2)\)时获得的最大收益。复杂度\(O(n^4)\),不行。我们换种方法,定义\(f_{st,x,y}\)表示两人同时走了\(st\)步,分别向右走了\(x,y\)步。显然如果向右的步数确定了,向下的也确定了。转移方程如下:\[f_{st,x......
  • 题解 CF1265E
    期望DP。定义\(f_i\)表示第\(i\)个镜子照成功的期望天数,\(p_i\)为第\(i\)天成功的概率,\(q_i\)为第\(i\)天失败的概率。根据题意容易列出方程:\[f_i=(f_{i-1}+1)\cdotp_i+(f_{i-1}+1+f_i)\cdotq_i\]移项得:\[(1-q_i)\cdotf_i=(f_{i-1}+1)\cdot(p_i+q_i)\]同除以......
  • 题解 CF930C
    好题啊好题。定义\(a_i\)为有多少个区间包含\(i\)。拍脑袋一想,当且仅当存在顺序的三个坐标\((i,j,k)\)满足\(a_i>a_j\)且\(a_j<a_l\)时,可以确定没有数被所有区间包含。这个结论很简单,因为如果存在,则\(a\)序列必定为一个“山峰”。而如果出现上面这种情况,说明有“山......