十二省联考2019 春节十二响
本质上也是傻逼题,全场切的那种。
但是一开始想不到,然后怎么想到呢?
“注意:在第 10、11、12 号测试点中,1 号子程序不一定是链的一个端点。”
我就看了一眼树是一条链的部分分
哇傻逼玩意儿啊,不是两边sort一下答案就是\(\sum \max\)吗
然后想想不是一条链怎么做
首先可以想到树形dp,那么一个子树树根肯定只能单独拿出来,所以不管了
然后根据套路想怎么合并两个儿子
???好像就是两个儿子sort以后前面一段\(\max\)啊
然后拿个堆维护这玩意儿,启发式合并一下就完事了
#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il ll gi(){
ll x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-')f=-1;
ch=getchar();
}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
int M[200010],fir[200010],dis[400010],nxt[400010],id;
il vd link(int a,int b){nxt[++id]=fir[a],fir[a]=id,dis[id]=b;}
std::priority_queue<int>que[200010];
il vd dfs(int x,int fa=-1){
for(int i=fir[x];i;i=nxt[i]){
if(fa==dis[i])continue;
dfs(dis[i],x);
if(que[x].size()<que[dis[i]].size())que[x].swap(que[dis[i]]);
std::vector<int>merged;
while(!que[dis[i]].empty())merged.push_back(std::max(que[x].top(),que[dis[i]].top())),que[x].pop(),que[dis[i]].pop();
for(auto j:merged)que[x].push(j);
}
que[x].push(M[x]);
}
int main(){
#ifdef XZZSB
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int n=gi();
for(int i=1;i<=n;++i)M[i]=gi();
for(int i=2;i<=n;++i)link(gi(),i);
dfs(1);
ll ans=0;
while(!que[1].empty())ans+=que[1].top(),que[1].pop();
printf("%lld\n",ans);
return 0;
}