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

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

  2. JS变量作用域与解构赋值

    用var变量是有作用域的 变量在函数内部声明时,那么该变量只属于整个函数体,函数外不可调用 当两个不同的函数里,使用了用一个相同的变量名,二者不互相影响,相互独立 遇到嵌套函数时,外部函数不可调用内部 ...

  3. C1. Pokémon Army (easy version) 解析(DP)

    Codeforce 1420 C1. Pokémon Army (easy version) 解析(DP) 今天我們來看看CF1420C1 題目連結 題目 對於一個數列\(a\),選若干個數字,求al ...

  4. 【转】Setting up SDL on Windows

    FROM: http://lazyfoo.net/tutorials/SDL/01_hello_SDL/windows/index.php Setting up SDL on Windows Last ...

  5. 循序渐进VUE+Element 前端应用开发(25)--- 各种界面组件的使用(1)

    在我们使用Vue+Element开发前端的时候,往往涉及到很多界面组件的使用,其中很多直接采用Element官方的案例即可,有些则是在这个基础上封装更好利用.更少代码的组件:另外有些则是直接采用第三方 ...

  6. 水题挑战2 :NOIP提高组 2011 聪明的质监员

    小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 \(n\) 个矿石,从\(1\) 到 \(n\) 逐一编号,每个矿石都有自己的重量 \(w_i\) 以及价值 \(v_i\) .检验矿 ...

  7. Hash 算法与 Manacher 算法

    目录 前言 简单介绍 简述 Hash 冲突 离散化 基本结构 普通 Hash 简述 例题 字符串 Hash 简单介绍 核心思想 基本运算 二维字符串 Hash 例题 兔子与兔子 回文子串的最大长度 后 ...

  8. 【Luogu】 P6274 [eJOI2017]六 题解

    首先,题目说了最多\(6\)个质因数. 如此小的数据范围,不是状压还是啥? 然后,我们可以发现一个性质:只要两个因数有相同的质因数(不管次数是多少),两者就不互质. 这启示我们用一个二进制数来表示一类 ...

  9. ACM已刷题

    ZOJ: 1001.1002.1003.1004.1005.1006.1037.1045.1048.1049.1067.1087.1091.1016. swjtuoj: 2433 注:没链接的应该是最 ...

  10. 分布式文档存储数据库之MongoDB基础入门

    一.MongoDB简介 MongoDB是用c++语言开发的一款易扩展,易伸缩,高性能,开源的,schema free 的基于文档的nosql数据库:所谓nosql是指不仅仅是sql的意思,它拥有部分s ...