题意:
有
一
棵
树
代
表
敌
人
的
分
级
网
络
,
n
个
结
点
有一棵树代表敌人的分级网络,n个结点
有一棵树代表敌人的分级网络,n个结点
从
上
到
下
依
次
等
级
地
位
下
降
,
每
个
结
点
代
表
一
个
部
队
从上到下依次等级地位下降,每个结点代表一个部队
从上到下依次等级地位下降,每个结点代表一个部队
每
个
部
队
有
攻
击
力
a
i
,
每
次
可
以
使
一
个
结
点
的
攻
击
力
减
少
p
每个部队有攻击力a_i,每次可以使一个结点的攻击力减少p
每个部队有攻击力ai,每次可以使一个结点的攻击力减少p
同
时
这
个
结
点
的
子
节
点
会
减
少
p
−
d
i
s
(
i
,
j
)
2
同时这个结点的子节点会减少p-dis(i,j)^2
同时这个结点的子节点会减少p−dis(i,j)2
如
果
攻
击
力
小
于
0
,
那
么
将
被
歼
灭
如果攻击力小于0,那么将被歼灭
如果攻击力小于0,那么将被歼灭
只
能
对
未
被
歼
灭
的
部
队
发
动
进
攻
只能对未被歼灭的部队发动进攻
只能对未被歼灭的部队发动进攻
问
最
多
多
少
次
能
够
歼
灭
这
个
军
队
问最多多少次能够歼灭这个军队
问最多多少次能够歼灭这个军队
题解:
n
<
=
1
e
6
,
a
i
<
=
1
e
9
n<=1e6,a_i<=1e9
n<=1e6,ai<=1e9
由
于
是
个
树
,
而
且
儿
子
和
父
亲
有
关
系
由于是个树,而且儿子和父亲有关系
由于是个树,而且儿子和父亲有关系
最
先
考
虑
的
就
是
D
F
S
遍
历
然
后
进
行
状
态
转
移
最先考虑的就是DFS遍历然后进行状态转移
最先考虑的就是DFS遍历然后进行状态转移
如
果
攻
击
父
结
点
,
就
会
对
子
结
点
造
成
伤
害
如果攻击父结点,就会对子结点造成伤害
如果攻击父结点,就会对子结点造成伤害
这
个
伤
害
值
为
p
−
d
i
s
(
i
,
j
)
2
这个伤害值为p-dis(i,j)^2
这个伤害值为p−dis(i,j)2
对
这
个
进
行
化
简
,
可
以
得
到
p
−
(
d
j
−
d
i
)
2
对这个进行化简,可以得到p-(d_j-d_i)^2
对这个进行化简,可以得到p−(dj−di)2
(
d
表
示
结
点
的
深
度
)
(d表示结点的深度)
(d表示结点的深度)
所
以
现
在
需
要
看
的
就
是
每
个
父
亲
对
该
结
点
的
影
响
所以现在需要看的就是每个父亲对该结点的影响
所以现在需要看的就是每个父亲对该结点的影响
通
过
这
个
式
子
我
们
可
以
发
现
超
过
父
结
点
只
能
对
一
定
距
离
的
子
节
点
造
成
伤
害
通过这个式子我们可以发现超过父结点只能对一定距离的子节点造成伤害
通过这个式子我们可以发现超过父结点只能对一定距离的子节点造成伤害
这
个
距
离
就
是
p
,
对
于
每
个
儿
子
将
多
余
的
影
响
减
去
这个距离就是\sqrt{p},对于每个儿子将多余的影响减去
这个距离就是p,对于每个儿子将多余的影响减去
每
个
儿
子
最
多
收
到
这
么
多
深
度
的
影
响
每个儿子最多收到这么多深度的影响
每个儿子最多收到这么多深度的影响
然
后
把
上
述
式
子
化
简
然后把上述式子化简
然后把上述式子化简
p
−
(
d
j
2
−
2
∗
d
i
∗
d
j
+
d
i
2
)
p-(d_j^2-2*d_i*d_j+d_i^2)
p−(dj2−2∗di∗dj+di2)
这
样
就
发
现
,
其
实
对
于
每
个
子
结
点
这样就发现,其实对于每个子结点
这样就发现,其实对于每个子结点
只
和
上
述
结
点
的
攻
击
次
数
,
深
度
和
深
度
的
平
方
有
关
系
只和上述结点的攻击次数,深度和深度的平方有关系
只和上述结点的攻击次数,深度和深度的平方有关系
所
以
直
接
用
树
形
d
p
维
护
这
些
值
所以直接用树形dp维护这些值
所以直接用树形dp维护这些值
但
是
由
于
刚
才
算
的
最
远
距
离
,
所
以
每
次
超
出
这
个
距
离
的
时
候
需
要
减
去
但是由于刚才算的最远距离,所以每次超出这个距离的时候需要减去
但是由于刚才算的最远距离,所以每次超出这个距离的时候需要减去
每
次
贪
心
对
尽
量
靠
上
的
结
点
进
行
攻
击
每次贪心对尽量靠上的结点进行攻击
每次贪心对尽量靠上的结点进行攻击
最
后
计
算
攻
击
次
数
最后计算攻击次数
最后计算攻击次数
AC代码
/*
Author:zzugzx
Lang:C++
Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
#define SZ(x) (int)x.size()
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
const int mod=1e9+7;
//const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[][2]={{0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1}};
ll ans,n,p,lim;
vector<int> g[maxn];
ll s1[maxn],s2[maxn],s[maxn],cnt[maxn],a[maxn],tot[maxn];
void dfs(int u,int fa,ll d){
if(d>lim){
ll t=d-lim;
s[u]-=cnt[t];
s1[u]-=cnt[t]*t;
s2[u]-=cnt[t]*t*t;
}
ll tmp=s[u]*(p-d*d)-s2[u]+2*d*s1[u];
if(a[u]>=tmp)tot[u]=(a[u]-tmp)/p+1,ans+=tot[u];
cnt[d]=tot[u];
for(auto v:g[u]){
if(v==fa)continue;
s[v]=s[u]+tot[u];
s1[v]=s1[u]+tot[u]*d;
s2[v]=s2[u]+tot[u]*d*d;
dfs(v,u,d+1);
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n>>p;lim=sqrt(p-1)+1;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
g[u].pb(v);
g[v].pb(u);
}
dfs(1,0,1);
cout<<ans;
return 0;
}