dsu on tree

题目链接

点我跳转

题目大意

给你一棵以\(1\)为根节点,包含\(n\)个节点的树和一个参数 \(k\),求每个节点的"\(rating\)"

\(rating\) 值的计算方式是这样的,对于\(u\)的子树中的所有节点,如果\(x,y\)满足\(dis(x,y) = k\)

并且\(x,y\)的最近公共祖先是\(u\)且满足\(u != x , u != y\),那么\(u\)的\(rating\)就会增加\(a_x + a_y\)

解题思路

因为 \(x , y\) 的最近公共祖先为 \(u\) ,所以 \(x , y\) 一定在 \(u\) 子树的不同分支

\(dis(x,y) = k\) 等价于 \(dep[x] + dep[y] - 2 × dep[lca(x,y)] = k\)

于是可以先用 cnt[dep] 记录深度为 dep 的节点出现的次数,用 sum[dep] 记录 dep 的节点的权值和

那么对于 \(rt\) 为根的子节点 \(u\),与其相匹配的点的深度为 \(d = k + 2 * dep[rt] - dep[u]\)

它对 \(rt\) 产生的贡献就为 \(cnt_d × a_u\) ,而深度为 \(d\) 的点因为 \(u\) 的出现对 \(rt\) 的贡献都会翻倍

所以 \(u\) 节点的出现对 \(rt\) 的总贡献为 \(sum[d] + a[u] * cnt[d]\)

又因为与 \(u\) 节点产生贡献的节点必须和 \(u\) 不在一个分支,即一个分支内的任意节点不能相互影响

所以需要先对一个分支统计完贡献后,再添加它的信息

我们AC_Code

#include<bits/stdc++.h>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define int long long
using namespace std;
const int N = 3e5 + 10;
struct Edge{
int nex , to;
}edge[N << 1];
int head[N] , TOT;
void add_edge(int u , int v)
{
edge[++ TOT].nex = head[u] ;
edge[TOT].to = v;
head[u] = TOT;
}
int n , k , sum[N] , cnt[N] , ans[N];
int dep[N] , sz[N] , HH , hson[N] , f[N][30] , a[N];
void dfs(int u , int far)
{
sz[u] = 1;
dep[u] = dep[far] + 1;
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far) continue ;
dfs(v , u);
sz[u] += sz[v];
if(sz[v] > sz[hson[u]]) hson[u] = v;
}
}
void change(int u , int far , int val)
{
sum[dep[u]] += val * a[u];
cnt[dep[u]] += val;
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far || v == HH) continue ;
change(v , u , val);
}
}
void calc(int u , int far , int rt)
{
int c = k + 2 * dep[rt] - dep[u];
if(c < 0) return ;
ans[rt] += sum[c] + a[u] * cnt[c];
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far || v == HH) continue ;
calc(v , u , rt);
}
}
void dsu(int u , int far , int op)
{
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far || v == hson[u]) continue ;
dsu(v , u , 0);
}
if(hson[u]) dsu(hson[u] , u , 1) , HH = hson[u];
for(int i = head[u] ; i ; i = edge[i].nex)
{
int v = edge[i].to;
if(v == far || v == HH) continue ;
calc(v , u , u) , change(v , u , 1);
}
HH = 0;
sum[dep[u]] += a[u] , cnt[dep[u]] ++ ;
if(!op)
{
change(u , far , -1);
}
}
signed main()
{
cin >> n >> k;
rep(i , 1 , n) cin >> a[i];
rep(i , 2 , n)
{
int u , v;
cin >> u >> v;
add_edge(u , v) , add_edge(v , u);
}
dfs(1 , 0);
dsu(1 , 0 , 0);
rep(i , 1 , n) cout << ans[i] << " \n"[i == n];
return 0;
}

牛客练习赛60E 旗鼓相当的对手的更多相关文章

  1. 牛客练习赛31 B 赞迪卡之声妮莎与奥札奇 逻辑,博弈 B

    牛客练习赛31 B 赞迪卡之声妮莎与奥札奇 https://ac.nowcoder.com/acm/contest/218/B 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 2621 ...

  2. 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D

    目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...

  3. 牛客练习赛31 D 神器大师泰兹瑞与威穆 STL,模拟 A

    牛客练习赛31 D 神器大师泰兹瑞与威穆 https://ac.nowcoder.com/acm/contest/218/D 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 26214 ...

  4. 最小生成树--牛客练习赛43-C

    牛客练习赛43-C 链接: https://ac.nowcoder.com/acm/contest/548/C 来源:牛客网 题目描述 ​ 立华奏是一个刚刚开始学习 OI 的萌新. 最近,实力强大的 ...

  5. 牛客练习赛28-B(线段树,区间更新)

    牛客练习赛28 - B 传送门 题目 qn姐姐最好了~ ​ qn姐姐给你了一个长度为n的序列还有m次操作让你玩, ​ 1 l r 询问区间[l,r]内的元素和 ​ 2 l r 询问区间[l,r]内的 ...

  6. 牛客练习赛26:D-xor序列(线性基)

    链接:牛客练习赛26:D-xor序列(线性基) 题意:小a有n个数,他提出了一个很有意思的问题:他想知道对于任意的x, y,能否将x与这n个数中的任意多个数异或任意多次后变为y 题解:线性基 #inc ...

  7. [堆+贪心]牛客练习赛40-B

    传送门:牛客练习赛40 题面: 小A手头有 n 份任务,他可以以任意顺序完成这些任务,只有完成当前的任务后,他才能做下一个任务 第 i 个任务需要花费  x_i 的时间,同时完成第 i 个任务的时间不 ...

  8. 牛客练习赛 29 E 位运算?位运算!(线段树)

    题目链接  牛客练习赛29E 对$20$位分别建立线段树.首先$1$和$2$可以合起来搞(左移右移其实是等效的) 用个lazy标记下.转移的时候加个中间变量. $3$和$4$其实就是区间$01$覆盖操 ...

  9. 牛客练习赛22C Bitset

    牛客练习赛22C 一共有 n个数,第 i 个数是 xi  xi 可以取 [li , ri] 中任意的一个值. 设 ,求 S 种类数. 感觉二进制真是一个神奇的东西. #include <iost ...

随机推荐

  1. 阿里技术专家十五问,真题面试刀刀见肉,快来和阿里面试官battle

    引言 2020阿里巴巴专家组出题,等你来答: 题目:如何判断两个链表是否相交 出题人:阿里巴巴新零售技术质量部 参考答案: $O(n^2)$: 两层遍历,总能发现是否相交 $O(n)$: 一层遍历,遍 ...

  2. Vue +WebSocket + WaveSurferJS 实现H5聊天对话交互

    引言 在与实现了语音合成.语义分析.机器翻译等算法的后端交互时,页面可以设计成更为人性化.亲切的方式.我们采用类似于聊天对话的实现,效果如下: 智能客服(输入文本,返回引擎处理后的文本结果) 语音合成 ...

  3. OpenTelemetry架构介绍

    OpenTelemetry: 经得起考验的工具 摘自:https://blog.newrelic.com/product-news/what-is-opentelemetry/ 目录 OpenTele ...

  4. 【应用服务 App Service】App Service使用Git部署时,遇见500错误

    问题描述 Azure App Service在部署的时候支持多种方式,如Zip,VS 2019, VS Code,或者是Git部署,当使用Git部署遇见500错误时,可以通过其他的部署方式来验证是否也 ...

  5. 使用 Filebeat 对多行日志进行处理(multiline)

    Filebeat 收集日志的过程中,默认是按行收取的,也就是每一行都会默认是一个单独的事件并添加时间戳.但是在收集一些特殊日志的时候,往往一个事件包含有多行,例如 Java 的堆栈跟踪日志: 20-0 ...

  6. http接口和web service接口测试区别是什么?

    1.web service有一套完整的协议标准,其中有soap协议,用来进行消息的传递. 2.soap请求是HTTP POST的一个专用版本,遵循一种特殊的xml消息格式 Content-type设置 ...

  7. 4-Kotlin数据类型与变量

    一. 变量概念 在Kotlin中变量其实对应着内存中特定区域,变量就像是一个装"数据"的容器 1 val num1:Int = 100 2 var num2:Int = 99 关键 ...

  8. 模拟量采集模块433Mhz LoRa无线自组网络介绍

    模拟量采集模块433Mhz LoRa无线自组网络是LPWAN(低功耗广域网Low Power Wide Area Nerwork)通信技术中的一种,是美国Semtech公司采用和推广的一种基于扩频技术 ...

  9. python数据类型互相转换

    类型转换 关注公众号"轻松学编程"了解更多. 主要针对几种存储工具:list.tuple.dict.set 特殊之处:dict是用来存储键值对的. 1.list 转换为set l1 ...

  10. P2966 [USACO09DEC]Cow Toll Paths G

    题意描述 Cow Toll Paths G 这道题翻译的是真的不错,特别是第一句话 给定一张有 \(n\) 个点 \(m\) 条边的无向图,每条边有边权,每个点有点权. 两点之间的路径长度为所有边权 ...