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

Description

传送门

Solution

如果只有左右两条链,一定是左链和右链的最大配最大、次大配次大,两条链这样合并后就变成了一条链,然后继续按照这种方法跟其他的链匹配即可。

一开始是这么写的,但是迭代器 \(p\) 已经删掉了,再 --\(p\) 就会出奇怪的错误。

    p = s[a[u]].end(), q = s[a[e[i].v]].end(), --p, --q;
    for (;;) {
        if (*p < *q) s[a[u]].erase(p), s[a[u]].insert(*q);
        if (q == s[a[e[i].v]].begin()) break;
        --p, --q;
    }

Code

#include <queue>
#include <cstdio>
#include <algorithm>

const int N = 200005;
struct Edge { int v, nxt; } e[N];
int f[N], m[N], head[N], a[N], tot, s[N], t;
std::priority_queue<int> q[N];
long long ans;

int read() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + (c ^ 48), c = getchar();
    return x;
}
void adde(int u, int v) {
    e[++tot].nxt = head[u], head[u] = tot, e[tot].v = v;
}
void dfs(int u, int f) {
    a[u] = u;
    for (int i = head[u]; i; i = e[i].nxt) if (e[i].v != f) {
        dfs(e[i].v, u);
        if (q[a[e[i].v]].size() > q[a[u]].size()) std::swap(a[u], a[e[i].v]);
        while (!q[a[e[i].v]].empty())
            s[++t] = std::max(q[a[e[i].v]].top(), q[a[u]].top()), q[a[e[i].v]].pop(), q[a[u]].pop();
        while (t) q[a[u]].push(s[t]), --t;
    }
    q[a[u]].push(m[u]);
}
int main() {
    int n = read();
    for (int i = 1; i <= n; ++i) m[i] = read();
    for (int i = 2; i <= n; ++i) f[i] = read(), adde(f[i], i);
    dfs(1, 0);
    while (!q[a[1]].empty()) ans += q[a[1]].top(), q[a[1]].pop();
    printf("%lld\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fly-in-milkyway/p/10670053.html