[十二省联考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;
}