CF1988D The Omnipotent Monster Killer

CF1988D The Omnipotent Monster Killer

本文同步于我的网站

Problem

怪物们在一棵有 n n n 个顶点的树上,编号为 i ( 1 ≤ i ≤ n ) i(1\le i\le n) i(1in) 的怪物位于编号为 i i i 的顶点上,攻击力为 a i a_i ai 。你需要与怪物战斗 1 0 100 10^{100} 10100 个回合。在每个回合中,会依次发生以下两步:

  1. 所有活着的怪物攻击你。你的生命值会按照所有活体怪物攻击点的总和减少。
  2. 您选择一些(可以选全部,也可以不选)怪物并杀死它们。被杀死的怪物将不会再进行攻击。

限制条件:在一个回合内不能杀死相邻的两只怪物。

如果您以最佳选择方式攻击的怪物,那么在所有回合后,您的健康值减少的最小值是多少?

1 ≤ t ≤ 1 0 4 , 1 ≤ n ≤ 3 ⋅ 1 0 5 , 1 ≤ a i ≤ 1 0 12 , ∑ n ≤ 3 ⋅ 1 0 5 1\le t\le 10^4,1\le n\le 3\cdot 10^5,1\le a_i \le 10^{12},\sum n\le 3\cdot 10^5 1t104,1n3105,1ai1012,n3105

Solution

这是一道再经典不过的树形DP了。太惭愧了。

每个节点的贡献可以表示为 w i ⋅ a i w_i\cdot a_i wiai 的形式,其中 w i w_i wi 表示怪物 i i i 是第 w i w_i wi 次被杀死的。可以证明 w i w_i wi 不会超过 log ⁡ 2 ( n ) \log_2(n) log2(n)

图:Taibo

上图中,欲构造出 w i = x w_i=x wi=x 的点,需要将该点连接上 w = 1 , 2 , … , x − 1 w=1,2,\dots,x-1 w=1,2,,x1 的节点。设构造出 max ⁡ w i = n \max w_i=n maxwi=n 的树至少需要 t o t n tot_n totn​ 个节点,则存在
t o t n = { 1 n = 1 ∑ i = 1 n − 1 t o t i + 1 n ≥ 2 \begin{gather} tot_n= \begin{cases} & 1 & n=1\\ & \sum_{i=1}^{n-1}tot_i +1 & n\ge 2 \end{cases} \end{gather} totn={1i=1n1toti+1n=1n2
即得 t o t n = 2 n tot_n=2^n totn=2n 。也就是说对于一张 n n n 个节点的图,其至多需要 log ⁡ 2 ( n ) \log_2(n) log2(n) 次选择就可以将所有怪物杀死。

下面开始dp。设 d p x , k dp_{x,k} dpx,k 表示若第 k k k 次杀死怪物 x x x x x x 子树内的怪物至少会产生多少点伤害。

d p x , k dp_{x,k} dpx,k 由两部分组成:

  • 在第 k k k 次杀死怪物 x x x 之前,怪物 x x x 会产生 k ⋅ a x k\cdot a_x kax 点伤害。
  • x x x 的子树内的怪物(除了 x x x 本身)产生的伤害。

d p x , k = k ⋅ a x + ∑ y ∈ u ( x ) min ⁡ j ≠ k d p y , j \begin{gather} dp_{x,k}=k\cdot a_x + \sum_{y\in u(x)}\min_{j\not =k} dp_{y,j} \end{gather} dpx,k=kax+yu(x)j=kmindpy,j

其中 u ( x ) u(x) u(x) 表示点 x x x​ 的儿子节点。

最后答案为 min ⁡ d p r o o t , k \min dp_{root,k} mindproot,k

Code

#define N 300010

int n;
int head[N],nxt[N*2],ver[N*2],cnt;
void insert(int x,int y)
{
	nxt[++cnt]=head[x];
	head[x]=cnt;
	ver[cnt]=y;
}


LL a[N];

#define K 25
#define inf (1ll<<62)
LL dp[N][K+5];

void dfs(int x,int f)
{
	for(int i=1;i<=K;i++)
	{
		dp[x][i]=a[x]*i;
	}
	
	for(int i=head[x];i;i=nxt[i])
	{
		int y=ver[i];
		if(y==f) continue;
		dfs(y,x);
		for(int j=1;j<=K;j++)//点x将被第j次选
		{
			LL mn=inf;
			for(int k=1;k<=K;k++)//相邻点y将被第k次选
			{
				if(j!=k)
				{
					mn=min(mn,dp[y][k]);
				}
			}
			dp[x][j]+=mn;
		}
	}
}



int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cout.precision(10);
	int t=1;
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a[i];
		}
		for(int i=1;i<n;i++)
		{
			int x,y;cin>>x>>y;
			insert(x,y);
			insert(y,x);
		}
		
		dfs(1,0);
		
		LL ans=inf;
		for(int i=1;i<=K;i++)
		{
			ans=min(ans,dp[1][i]);
		}
		
		cout<<ans<<endl;
		
		
		for(int i=1;i<=cnt;i++)
		{
			head[i]=nxt[i]=ver[i]=0;
		}
		cnt=0;
	}
	return 0;
}

相关推荐

  1. CF1898B Milena and Admirer(贪心)

    2024-07-21 17:36:01       65 阅读
  2. CF1918 D. Blocking Elements [二分+数据结构优化dp]

    2024-07-21 17:36:01       51 阅读
  3. 水气表CJ/T188协议学习及实例

    2024-07-21 17:36:01       34 阅读
  4. <span style='color:red;'>CI</span>/<span style='color:red;'>CD</span>

    CI/CD

    2024-07-21 17:36:01      49 阅读
  5. _198打家劫舍

    2024-07-21 17:36:01       59 阅读
  6. Leetcode--198

    2024-07-21 17:36:01       39 阅读
  7. CF1895C

    2024-07-21 17:36:01       48 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-21 17:36:01       101 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-21 17:36:01       109 阅读
  3. 在Django里面运行非项目文件

    2024-07-21 17:36:01       87 阅读
  4. Python语言-面向对象

    2024-07-21 17:36:01       96 阅读

热门阅读

  1. resultMap

    2024-07-21 17:36:01       20 阅读
  2. Python编程防止计算机休眠,保持唤醒状态

    2024-07-21 17:36:01       22 阅读
  3. 力扣题解(盈利计划)

    2024-07-21 17:36:01       21 阅读
  4. Mysql在linux安装报错

    2024-07-21 17:36:01       23 阅读
  5. 大型网站核心架构要素

    2024-07-21 17:36:01       25 阅读
  6. 看过来!看过来!python九大数据类型大整合!

    2024-07-21 17:36:01       19 阅读
  7. centos软件安装

    2024-07-21 17:36:01       25 阅读
  8. 内存屏障:程序员的“隐形护盾”

    2024-07-21 17:36:01       25 阅读
  9. 比较 WordPress 的 Baklib 和 BetterDocs

    2024-07-21 17:36:01       25 阅读