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

  1. #include<bits/stdc++.h>
  2. #define rep(i,a,n) for (int i=a;i<=n;i++)
  3. #define int long long
  4. using namespace std;
  5. const int N = 3e5 + 10;
  6. struct Edge{
  7. int nex , to;
  8. }edge[N << 1];
  9. int head[N] , TOT;
  10. void add_edge(int u , int v)
  11. {
  12. edge[++ TOT].nex = head[u] ;
  13. edge[TOT].to = v;
  14. head[u] = TOT;
  15. }
  16. int n , k , sum[N] , cnt[N] , ans[N];
  17. int dep[N] , sz[N] , HH , hson[N] , f[N][30] , a[N];
  18. void dfs(int u , int far)
  19. {
  20. sz[u] = 1;
  21. dep[u] = dep[far] + 1;
  22. for(int i = head[u] ; i ; i = edge[i].nex)
  23. {
  24. int v = edge[i].to;
  25. if(v == far) continue ;
  26. dfs(v , u);
  27. sz[u] += sz[v];
  28. if(sz[v] > sz[hson[u]]) hson[u] = v;
  29. }
  30. }
  31. void change(int u , int far , int val)
  32. {
  33. sum[dep[u]] += val * a[u];
  34. cnt[dep[u]] += val;
  35. for(int i = head[u] ; i ; i = edge[i].nex)
  36. {
  37. int v = edge[i].to;
  38. if(v == far || v == HH) continue ;
  39. change(v , u , val);
  40. }
  41. }
  42. void calc(int u , int far , int rt)
  43. {
  44. int c = k + 2 * dep[rt] - dep[u];
  45. if(c < 0) return ;
  46. ans[rt] += sum[c] + a[u] * cnt[c];
  47. for(int i = head[u] ; i ; i = edge[i].nex)
  48. {
  49. int v = edge[i].to;
  50. if(v == far || v == HH) continue ;
  51. calc(v , u , rt);
  52. }
  53. }
  54. void dsu(int u , int far , int op)
  55. {
  56. for(int i = head[u] ; i ; i = edge[i].nex)
  57. {
  58. int v = edge[i].to;
  59. if(v == far || v == hson[u]) continue ;
  60. dsu(v , u , 0);
  61. }
  62. if(hson[u]) dsu(hson[u] , u , 1) , HH = hson[u];
  63. for(int i = head[u] ; i ; i = edge[i].nex)
  64. {
  65. int v = edge[i].to;
  66. if(v == far || v == HH) continue ;
  67. calc(v , u , u) , change(v , u , 1);
  68. }
  69. HH = 0;
  70. sum[dep[u]] += a[u] , cnt[dep[u]] ++ ;
  71. if(!op)
  72. {
  73. change(u , far , -1);
  74. }
  75. }
  76. signed main()
  77. {
  78. cin >> n >> k;
  79. rep(i , 1 , n) cin >> a[i];
  80. rep(i , 2 , n)
  81. {
  82. int u , v;
  83. cin >> u >> v;
  84. add_edge(u , v) , add_edge(v , u);
  85. }
  86. dfs(1 , 0);
  87. dsu(1 , 0 , 0);
  88. rep(i , 1 , n) cout << ans[i] << " \n"[i == n];
  89. return 0;
  90. }

牛客练习赛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. Unity实现代码控制音频播放

    前言 很久没说过Unity了,现在说一下Unity用代码控制音频播放 准备工作 1.需要播放的音频 2.给需要加声音的对象加Audio Source组件 3.新建Play脚本,并绑定需要播放声音的对象 ...

  2. pyqt5安装报错解决办法

    用国内快速的镜像源即可 pip install PyQt5 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

  3. 理解DES算法

    首先 了解对称密码加密技术:采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密.但是有时候密钥不用完全相同 只要相似也可以.因为用一个密钥可 ...

  4. Java之HttpClient调用WebService接口发送短信源码实战

    摘要 Java之HttpClient调用WebService接口发送短信源码实战 一:接口文档 二:WSDL 三:HttpClient方法 HttpClient方法一 HttpClient方法二 Ht ...

  5. 编写shell脚本的规范

    目录 编写shell脚本的一些规范 解释器 添加脚本版本和注释功能 添加脚本调试 变量命名 全局变量和局部变量 命名规范 函数命名 脚本命名 函数 引用模块或文件 脚本日志 配置文件 其他 编写she ...

  6. scrapy反反爬虫

    反反爬虫相关机制 Some websites implement certain measures to prevent bots from crawling them, with varying d ...

  7. IDEA创建maven项目没有src/main/java目录问题解决

    IDEA创建maven项目没有src/main/java目录问题解决          今天新建一个maven项目的时候,没有src文件目录,查了网上很多,依然没有解决,后来发现是VM Options ...

  8. [开源] .Net 使用 ORM 访问 华为GaussDB数据库

    前言 华为GaussDB是一个企业级AI-Native分布式数据库.GaussDB采用MPP(Massive Parallel Processing)架构,支持行存储与列存储,提供PB(Petabyt ...

  9. Python 列表的11个重要操作

    列表是python中内置的数据结构,它的表现形式为方括号中不同数据的集合,用逗号分隔开.列表可以用来存储相同数据类型或不同数据类型. 列表是可变的,这也是它如此常用的原因,然而在某些情况下,可变性需要 ...

  10. hadoop之yarn(优化篇)

    最近一直在学习hadoop的一些原理和优化,然后也做了一些实践,也有没有去做实践的,反正个人观点都记录下来 一.yarn的介绍 YARN的基本结构由一个ResourceManager与多个NodeMa ...