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. 记录Spring Boot 2.3.4.RELEASE版注解方式实现AOP和通知的执行顺序

    1.advice 按照以下的顺序执行 输出结果:(正常和异常) 说明:Spring boot 2.3.4.RELEASE 版本使用的AOP是spring-aop-5.2.9.RELEASE,AOP的通 ...

  2. 循序渐进VUE+Element 前端应用开发(21)--- 省市区县联动处理的组件使用

    在很多应用中,往往都涉及到记录用户所在省份.城市.区县或者街道等信息,一般我们可以通过联动的Select或者类似的界面组件进行展示,或者使用Element中的el-cascader界面组件进行展示,而 ...

  3. 干货分享:一键网络重装系统 - 魔改版(适用于Linux / Windows)

      简介 一键网络重装系统 - 魔改版,它可以通过Internet重新安装Linux和Windows以及常见的操作系统.例如:Linux(CentOS,Debian,Ubuntu.etc..),Win ...

  4. vue 中v-if 与v-show 的区别

    相同点或者说功能,都可以动态操作dom元素的显示隐藏 不同点: 1.手段:v-if是动态的向DOM树内添加或者删除DOM元素:v-show是通过设置DOM元素的display样式属性控制显隐: 2.编 ...

  5. 给html添加图标

    <link rel="icon" type="image/ico" href="images/favicon.ico" />

  6. Filebeat 根据不同的日志设置不同的索引

    平时在物理机上使用 Filebeat 收集日志时,会编写多个 filebeat 配置文件然后启动多个 filebeat 进程来收集不同路径下的日志并设置相对应的索引.那么如果将所有的日志路径都写到一个 ...

  7. 每日10句:day1

    1,plt.style.use('ggplot') #使用R语言的图像配色方案 2,for a,b in zip(x,y): plt.text(a,b+1,'%.0f'%b,ha='center',v ...

  8. 华为hcip学习备考心得

    大家好我是林中鸟,经过几个月的学习终于顺利拿下了华为的hcip:写这篇文章主要目的是想和大家分享一下我学习备考中的一些经历. 2020年由于疫情影响,社会各行各业都遭受重创,同时也打乱的我的生活规划: ...

  9. Arduino IDE搭建ESP8266开发环境,文件下载过慢解决方法 | ESP-01制作WiFi开关教程,改造宿舍灯

    1. Arduino IDE配置ESP8266环境 参考:https://www.jianshu.com/p/cb0274d612b5 首先从 Arduino 官网 下载最新版本的 Arduino I ...

  10. Go语言如何像foreach一样有序遍历map

    目录 问题 解决 给key排序思路 开源实现 问题 Go语言的Map是无序遍历的,遍历一个map代码如下 package main import ( "fmt" ) func ma ...