首页 > 其他分享 >D. The Omnipotent Monster Killer

D. The Omnipotent Monster Killer

时间:2024-07-16 21:21:20浏览次数:6  
标签:10 Omnipotent Killer vertex monsters health first round Monster

D. The Omnipotent Monster Killer

You, the monster killer, want to kill a group of monsters. The monsters are on a tree with $n$ vertices. On vertex with number $i$ ($1\le i\le n$), there is a monster with $a_i$ attack points. You want to battle with monsters for $10^{100}$ rounds.

In each round, the following happens in order:

  1. All living monsters attack you. Your health decreases by the sum of attack points of all living monsters.
  2. You select some (possibly all or none) monsters and kill them. After being killed, the monster will not be able to do any attacks in the future.

There is a restriction: in one round, you cannot kill two monsters that are directly connected by an edge.

If you choose what monsters to attack optimally, what is the smallest health decrement you can have after all rounds?

Input

Each test contains multiple test cases. The first line contains the number of test cases $t$ ($1 \le t \le 10^4$). Description of the test cases follows.

The first line of each test case contains an integer $n$ ($1\le n\le 3\cdot 10^5$).

The second line of each test case contains $n$ integers $a_1,\ldots,a_n$ ($1\le a_i\le 10^{12}$).

The following $n-1$ lines each contain two integers $x,y$ ($1\le x,y\le n$), denoting an edge on the tree connecting vertex $x$ and $y$.

It is guaranteed that the sum of $n$ over all test cases does not exceed $3\cdot 10^5$.

Output

For each test case, print one integer: the minimum possible health decrement.

Example

input

3
1
1000000000000
5
47 15 32 29 23
1 2
1 3
2 4
2 5
7
8 10 2 3 5 7 4
1 2
1 4
3 2
5 3
6 2
7 5

output

1000000000000
193
57

Note

In the first test case, an optimal sequence of operations would be:

  • In the first round: first, receive the attack from the monster on vertex $1$, so your health decreases by $10^{12}$. Then kill the monster on vertex $1$.
  • In the second round to the $10^{100}$-th round: all monsters have been killed, so nothing happens.

The total health decrement is $10^{12}$.

In the second test case, an optimal sequence of operations would be:

  • In the first round: first, receive the attack from the monster on vertex $1,2,3,4,5$, so your health decreases by $47+15+32+29+23=146$. Then kill the monsters on vertex $1,4,5$.
  • In the second round: first, receive the attack from the monster on vertex $2,3$, so your health decreases by $15+32=47$. Then kill the monsters on vertex $2,3$.
  • In the third round to the $10^{100}$-th round: all monsters have been killed, so nothing happens.

The total health decrement is $193$.

In the third test case, an optimal sequence of operations would be:

  • In the first round: first, receive the attack from the monster on vertex $1,2,3,4,5,6,7$, so your health decreases by $8+10+2+3+5+7+4=39$. Then kill the monsters on vertex $1,3,6,7$.
  • In the second round: first, receive the attack from the monster on vertex $2,4,5$, so your health decreases by $10+3+5=18$. Then kill the monsters on vertex $2,4,5$.
  • In the third round to the $10^{100}$-th round: all monsters have been killed, so nothing happens.

The total health decrement is $57$.

 

解题思路

  不猜的话很难想到做法,就是最多操作 $O( \log n )$ 轮就能把所有怪物消灭。在这基础上就可以 dp 求解答案了。

  为了方便这里固定节点 $1$ 为树根。定义 $f(u,i)$ 表示消灭以 $u$ 为根的子树且 $u$ 在第 $i$ 轮被消灭所造成的最小代价,状态转移方程就是 $f(u,i) = i \cdot a_u + \sum\limits_{v \in \text{son}(u)} \min\limits_{j \ne i} \left\{ f(v,j) \right\}$。其中为了方便这里定义 $i$ 和 $j$ 的取值范围是 $1 \sim 20$(至少取到 $19$)。整个 dp 的时间复杂度是 $O(n \log^2{n})$。

  在进行状态转移时,如果提前预处理出 $l_i = \min\limits_{1 \leq j \leq i} \{ f(u,i) \}$ 和 $r_i = \min\limits_{i \leq j \leq 20} \{ f(u,i) \}$,那么状态转移方程就变成 $f(u,i) = i \cdot a_u +  \sum\limits_{v \in \text{son}(u)} \min\left\{ l_{i-1}, r_{i+1} \right\}$,时间复杂度降到 $O(n \log{n})$。

  最后大概解释一下官方题解中关于最多操作 $\lfloor \log{n} \rfloor + 1$ 轮就能把所有怪物消灭的证明。首先有一个贪心的结论,定义 $b_u$ 表示在最优解中节点 $u$ 是在哪轮被消灭的,假设已知其每个儿子 $v$ 的 $b_v$,那么一定有 $b_u = \underset{v \in \text{son}(u)}{\mathrm{mex}}\{b_v\}$。在保证 $b_u \ne b_v$ 的前提下,当然是希望节点 $u$ 越早被消灭。

  现在假设节点 $u$ 的 $b_u = x$ 最大,并将 $u$ 定为整棵树的根节点,由上面的结论知道 $u$ 的所有儿子的 $b_v$ 必定包含了 $1 \sim x-1$ 的所有取值。定义 $f(x)$ 表示根节点在第 $x$ 轮被消灭的树中,至少包含的节点数量。那么有 $f(x) \geq 1 + \sum\limits_{i=1}^{x-1}{f(i)} = 2^{x-2}\left(1 + f(1)\right) = 2^{x-1}$。$f(x)$ 最大取 $3 \cdot 10^{5}$,因此反推得到 $x \leq \lfloor \log{3 \cdot 10^{5}} \rfloor + 1 = 19$。

  AC 代码如下,时间复杂度为 $O(n \log{n})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 3e5 + 5, M = N * 2;

LL a[N];
int h[N], e[M], ne[M], idx;
LL f[N][25], l[25], r[25];

void add(int u, int v) {
    e[idx] = v, ne[idx] = h[u], h[u] = idx++;
}

void dfs(int u, int p) {
    for (int i = 1; i <= 20; i++) {
        f[u][i] = i * a[u];
    }
    for (int i = h[u]; i != -1; i = ne[i]) {
        int v = e[i];
        if (v == p) continue;
        dfs(v, u);
        l[0] = r[21] = 1e18;
        for (int i = 1; i <= 20; i++) {
            l[i] = min(l[i - 1], f[v][i]);
        }
        for (int i = 20; i; i--) {
            r[i] = min(r[i + 1], f[v][i]);
        }
        for (int i = 1; i <= 20; i++) {
            f[u][i] += min(l[i - 1], r[i + 1]);
        }
    }
}

void solve() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", a + i);
    }
    idx = 0;
    memset(h, -1, n + 1 << 2);
    for (int i = 0; i < n - 1; i++) {
        int u, v;
        scanf("%d %d", &u, &v);
        add(u, v), add(v, u);
    }
    dfs(1, 0);
    LL ret = 1e18;
    for (int i = 1; i <= 20; i++) {
        ret = min(ret, f[1][i]);
    }
    printf("%lld\n", ret);
}

int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  Editorial of Codeforces Round 958 (Div. 2):https://codeforces.com/blog/entry/131567

标签:10,Omnipotent,Killer,vertex,monsters,health,first,round,Monster
From: https://www.cnblogs.com/onlyblues/p/18306116

相关文章

  • BP插件暴破验证码实战流程(BP+captcha-killer-modified+ddddocr)
    含有速成版本+工具介绍及问题=保姆级版一、验证码破解流程:BP插件暴破实战流程如下:1、下载安装插件captcha-killer2、启动本地验证码识别服务ddddocr --codereg.py3、抓验证码的包,发送到插件4、配置识别服务模板5、抓登录的包,payload选插件,单线程本次使用到工具如下......
  • linux进程被杀掉日志,Linux进程突然被杀掉(OOM killer),查看系统日志
    Linux进程被杀掉(OOMkiller),查看系统日志基本概念:Linux内核有个机制叫OOMkiller(OutOfMemorykiller),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。内核检测到系统内存不足、挑选并杀掉某个进程的过程可以参考内核源代码......
  • D. Yet Another Monster Fight
    cf链接洛谷链接方法一最大最小值问题我们很容易想到二分答案法。那么我们如何写出check函数呢?对于答案x,若x-i+1<a[i],则选定怪物一定不在i位置左侧,即L=i;若x-n+i<a[i],则选定怪物一定不在i位置右侧,R=min(R,i)。遍历数组,如果L<=R则答案符合题意;否则不符合。code #includ......
  • [题解]AT_abc153_f [ABC153F] Silver Fox vs Monster
    模拟赛最后\(15\)分钟想到的做法。思路首先有一个显然的贪心策略:我们放炸弹的地方要尽可能的使这个炸弹能影响到更多的怪上。那么我们可以将对于一个怪\(i\)能够影响到它的区间表示出来\([\max(1,l_i-d),a_i+r]\)。然后将这些区间排个序,可以粗略画出这样的图:根据上......
  • CF1923B Monsters Attack! 题解
    题目简述数轴上有$n$个怪兽。最初第$i$个怪兽在$x_i$位置上,且血量为$a_i$。你在位置$0$上。在每秒钟会发生:你给任意怪兽发射总共$k$颗子弹,受到攻击的怪兽血量减一。血量小于等于$0$的怪兽死亡。没有死亡的怪兽向你移动一个单位。当一个怪兽来到你的位置,你就输......
  • 电脑技巧:推荐一款非常好用的文件重复清理工具DoubleKiller
    目录一、软件介绍二、功能介绍三、使用说明四、软件总结一、软件介绍DoubleKiller是一款专为用户解决重复文件问题而精心打造的小巧实用工具,安装包仅为1.2M。对于长期依赖电脑的工作者和电脑的职场人员来说,随着电脑使用时间的增长,电脑中难免会出现大量重复文件,这些......
  • Android 10.0 lowmemorykiller低内存时,禁止某个app被kill掉功能实现
    1.前言在10.0的系统定制化开发中,在对于系统lowmemorykiller低内存的时候,应用保活功能是非常重要的,就是在低内存的情况下禁止某个app被杀掉,所以就需要从lowmemorykiller机制入手,在杀进程的相关流程中进行分析来实现进程避免被杀掉,接下来就来实现这个功能2.lowmemorykiller低......
  • Pocket Monsters口袋怪兽 算法实现
    作业1.1-口袋怪兽关键信息您的任务这是一项个人开卷家庭作业。它涉及到与一个坏掉的游戏进行交互归结为一组编程问题。我们提供了一小组测试,允许您检查解决方案的正确性。然而,这些测试并不是详尽无遗的,通过测试也不是保证满分。您应该执行自己的测试,以确保您的解决方案已编码正确......
  • B. Monsters Attack!
    原题链接题解什么时候会输?首先我们要贪心一次性把离自己最近的怪物消灭掉,但是一回合内消灭掉了一个怪物之后还有剩余,我么就把剩余的扣在第二个离自己最近的怪物上如果我当前回合没有消灭怪物,并且怪物下一回合就到零点,那我就输了我们可以想象成这样的动画:我们每回合一次性往怪......
  • contest/1922 D Berserk Monster
    来来来,看看英语不好的我最开始理解的题目是怎么样的:(1)有一堆怪物在打架,每一次从左到右,一只怪物向离自己最近的怪物攻击一次,每一次怪物都攻击一次后会死掉多少只怪物。怎么做......(2)仔细阅读以后发现可能是所有怪物同时发动攻击。变简单了。(3)再阅读,发现所有怪物被攻击以后,受到的......