[十二省联考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
",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
",ans);
return 0;
}