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