散落星河的记忆🌠
Published on 2017-09-02 11:31 in 暂未分类 with 散落星河的记忆🌠

[十二省联考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;
}
posted @ 2019-04-08 14:19  散落星河的记忆🌠  阅读(162)  评论(0编辑  收藏  举报