luogu P5290 [十二省联考2019]春节十二响 优先队列_启发式合并
思维难度不大,在考上上写的启发式合并写错了,只拿了 60 pts,好难过QAQ
Code:
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <set>
#include <queue>
#define maxn 200001
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)
using namespace std;
priority_queue<int>Q[maxn];
int edges;
int n;
int head[maxn],to[maxn],nex[maxn],val[maxn],f[maxn];
void addedge(int u,int v){
nex[++edges] = head[u], head[u] = edges, to[edges] = v;
}
int tmp[maxn];
int id[maxn]; int idx;
void DFS(int u){
id[u]=++idx;
for(int v=head[u];v;v=nex[v]){
DFS(to[v]);
if(Q[id[u]].size() < Q[id[to[v]]].size()) swap(id[u],id[to[v]]);
int m=Q[id[to[v]]].size();
for(int i=1;i<=m;++i) {
tmp[i]=max(Q[id[u]].top(),Q[id[to[v]]].top());
Q[id[u]].pop(); Q[id[to[v]]].pop();
}
for(int i=1;i<=m;++i) Q[id[u]].push(tmp[i]);
}
Q[id[u]].push(val[u]);
}
int main(){
//setIO("spring");
scanf("%d",&n);
for(int i = 1;i <= n; ++i) scanf("%d",&val[i]);
for(int i = 2;i <= n; ++i) scanf("%d",&f[i]);
for(int i = 2;i <= n; ++i) addedge(f[i],i);
DFS(1);
long long ans = 0;
while(!Q[id[1]].empty())ans += (long long)Q[id[1]].top(), Q[id[1]].pop();
printf("%lld\n",ans);
return 0;
}