[十二省联考2019]春节十二响 题解

传送门

做完之后真的有一种 艹这么简单的题为什么我考场上没想出来 的感觉
当时在考场上已经被两个计数题的dp洗脑了,于是对着这道题推了半天的dp,最后写了个奇怪的记忆化搜索+一条链。然而写一条链的时候可能也只有我这种菜逼没看见题目里说1不一定是链的端点了。。。最后就只拿了45分
我要是能花时间好好想想一条链怎么做,这题就切了。因为一条链的情况实在是离正解很近很近。

一条链的做法:1号点至多两个分支,给每个分支开个堆,每次从两个堆里各弹一个值出来,取大的那个加入答案即可。
那么显然这个做法可以扩展到树上:给每个节点都开个堆,dfs的时候合并子树的堆即可。好像有大佬写左偏树写挂了,事实上这题只要启发式合并就行了。
于是代码真的是非常短

#include <cctype>
#include <cstdio>
#include <climits>
#include <algorithm>
#include <queue>

template <typename T> inline void read(T& x) {
    int f = 0, c = getchar(); x = 0;
    while (!isdigit(c)) f |= c == '-', c = getchar();
    while (isdigit(c)) x = x * 10 + c - 48, c = getchar();
    if (f) x = -x;
}
template <typename T, typename... Args>
inline void read(T& x, Args&... args) {
    read(x); read(args...); 
}
template <typename T> void write(T x) {
    if (x < 0) x = -x, putchar('-');
    if (x > 9) write(x / 10);
    putchar(x % 10 + 48);
}
template <typename T> inline void writeln(T x) { write(x); puts(""); }
template <typename T> inline bool chkmin(T& x, const T& y) { return y < x ? (x = y, true) : false; }
template <typename T> inline bool chkmax(T& x, const T& y) { return x < y ? (x = y, true) : false; }

typedef long long LL;
const int maxn = 2e5 + 207;

int v[maxn], head[maxn], next[maxn], a[maxn], tot;
std::priority_queue<int> heap[maxn];
int tmp[maxn];
int n;

inline void ae(int x, int y) {
    v[++tot] = y; next[tot] = head[x]; head[x] = tot;
}
void dfs(int x) {
    for (int i = head[x]; i; i = next[i]) {
        dfs(v[i]);
        if (heap[x].size() < heap[v[i]].size()) std::swap(heap[x], heap[v[i]]);
        while (!heap[v[i]].empty()) {
            tmp[++tmp[0]] = std::max(heap[x].top(), heap[v[i]].top());
            heap[x].pop(); heap[v[i]].pop();
        }
        while (tmp[0]) heap[x].push(tmp[tmp[0]--]);
    }
    heap[x].push(a[x]);
}

int main() {
    read(n);
    for (int i = 1; i <= n; ++i) read(a[i]);
    for (int i = 2, f; i <= n; ++i) read(f), ae(f, i);
    dfs(1);
    LL ans = 0;
    while (!heap[1].empty()) ans += heap[1].top(), heap[1].pop();
    writeln(ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39677783/article/details/89286773