一个特殊的启发式合并
大概是sz(a)+sz(b)=sz(max(a,b))
所以其实是一个log
//Love and Freedom. #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> #define ll long long #define inf 20021225 #define N 200100 using namespace std; struct edge{int to,lt;}e[N]; int in[N],cnt; int id[N],n; ll st[N],val[N]; priority_queue<ll> q[N]; void add(int x,int y) { e[++cnt].to=y; e[cnt].lt=in[x]; in[x]=cnt; } void dfs(int x) { id[x]=x; for(int i=in[x];i;i=e[i].lt) { int y=e[i].to; dfs(y); if(i==in[x]) id[x]=id[y]; else { if(q[id[x]].size()<q[id[y]].size()) swap(id[x],id[y]); int tot=0; while(!q[id[y]].empty()) st[++tot]=max(q[id[y]].top(),q[id[x]].top()),q[id[y]].pop(),q[id[x]].pop(); for(int i=1;i<=tot;i++) q[id[x]].push(st[i]); } } q[id[x]].push(val[x]); } int main() { scanf("%d",&n); int fa; for(int i=1;i<=n;i++) scanf("%lld",&val[i]); for(int i=2;i<=n;i++) scanf("%d",&fa),add(fa,i); dfs(1); ll ans=0; while(!q[id[1]].empty()) ans+=q[id[1]].top(),q[id[1]].pop(); printf("%lld ",ans); return 0; }