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

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

考场上最简单的一道题,可惜我没有想到合并(明明链都打出来了)

直接维护堆的启发式合并就好了

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cctype>
#include<vector>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
const int N = 2e5 + 3;
vector <int> G[N];
priority_queue <int> q[N];
int n,t;
int w[N],fa[N];
int rt[N];
int s[N];
int tot = 0;
inline int read(){
    int v = 0,c = 1;char ch = getchar();
    while(!isdigit(ch)){
        if(ch == '-') c = -1;
        ch = getchar();
    }
    while(isdigit(ch)){
        v = v * 10 + ch - 48;
         ch = getchar();	
    }
    return v * c;
}
inline void dfs(int x){
	vector <int> need; 
	if(!rt[x]) rt[x] = ++t;
	for(int i = 0;i < (int)G[x].size();++i){
		int y = G[x][i];
		if(y == fa[x]) continue;
		dfs(y);
		if(q[rt[y]].size() > q[rt[x]].size()) swap(rt[x],rt[y]);
	//	printf("%d %d\n",q[rt[y]].size() ,q[rt[x]].size() );
		for(;!q[rt[y]].empty();q[rt[x]].pop(),q[rt[y]].pop()) 
		need.push_back(max(q[rt[x]].top(),q[rt[y]].top()));
		for(int i = 0;i < (int)need.size();++i)
		q[rt[x]].push(need[i]);
		need.clear();
	}
	q[rt[x]].push(w[x]);
}
int main(){
	n = read();
	for(int i = 1;i <= n;++i) w[i] = read();
	for(int i = 2;i <= n;++i){
		fa[i] = read();
		G[fa[i]].push_back(i);
		G[i].push_back(fa[i]);	
	}
	dfs(1);
	long long ans = 0;
	for(;!q[rt[1]].empty();q[rt[1]].pop()) ans += q[rt[1]].top();
	printf("%lld\n",ans);
	return 0;
}
posted @ 2019-04-28 10:30  wyxdrqcccc  阅读(132)  评论(0编辑  收藏  举报