标签:sz 对手 ll deep fa LCA need 旗鼓相当
题:https://ac.nowcoder.com/acm/contest/4853/E
题意:对于一对点(u,v)要是dis(u,v)==k,就会对这对点的LCA产生a[x]+a[y]的贡献(LCA!=u&&LCA!=v)
分析:简单的dsu,把每个点当作LCA去统计子树深度个数,经过LCA的路径就是深度之和;
对于每个点u深度对应要达成k的深度要为2*deep[LCA]-deep[u]+k;
#include<bits/stdc++.h> using namespace std; #define pb push_back typedef long long ll; const int M=2e5+5; ll ans[M]; ll val[M],sz[M],son[M],a[M],cnt[M],deep[M]; ll k,n; vector<ll>g[M]; ll nownum; void dfs1(ll u,ll fa){ sz[u]=1; for(auto v:g[u]){ if(v!=fa){ deep[v]=deep[u]+1; dfs1(v,u); sz[u]+=sz[v]; if(sz[v]>sz[son[u]]) son[u]=v; } } } void add(ll u,ll fa,ll x){ cnt[deep[u]]+=x; val[deep[u]]+=x*a[u]; for(auto v:g[u]){ if(v!=fa) add(v,u,x); } } void cal(ll u,ll fa,ll LCA){ ll need=k+deep[LCA]*2-deep[u]; if(need>0){ nownum+=val[need]; nownum+=cnt[need]*a[u]; } for(auto v:g[u]) if(v!=fa) cal(v,u,LCA); } void dfs2(ll u,ll fa,ll sign){ //cout<<u<<endl; for(auto v:g[u]){ if(v!=fa&&son[u]!=v) dfs2(v,u,0); } if(son[u]) dfs2(son[u],u,1); for(auto v:g[u]) if(v!=fa&&v!=son[u]) cal(v,u,u),add(v,u,1); ans[u]=nownum; cnt[deep[u]]++,val[deep[u]]+=a[u]; if(!sign) add(u,fa,-1); nownum=0; } int main(){ scanf("%lld%lld",&n,&k); for(ll i=1;i<=n;i++) scanf("%lld",&a[i]); for(ll u,v,i=1;i<n;i++){ scanf("%lld%lld",&u,&v); g[u].pb(v); g[v].pb(u); } dfs1(1,0); dfs2(1,0,1); for(ll i=1;i<=n;i++) printf("%lld ",ans[i]); return 0; }View Code
标签:sz,对手,ll,deep,fa,LCA,need,旗鼓相当 来源: https://www.cnblogs.com/starve/p/12597621.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。