[十二省联考2019]春节十二响

                                  [十二省联考2019]春节十二响

 

Description

题目背景

「清明时节雨纷纷,路上行人欲断魂。」 2075 年的清明没有春雨。在漫天飞雪的笼罩下,穿行在冰原间的,只有载着人类微薄希望的雪地车。 遥遥 4.22 光年的征途,对于地球这孤独的旅人而言,恐怕也是无比寂寞的吧。

题目描述

距离苏拉威西只有一百公里了,车内的空气比窗外更加冰冷。四双眼睛紧盯着艾莉芬面前的屏幕,那是控制行星发动机的关键程序:春节十二响。他需要将其部署到电力控制系统的一个芯片中。 「春节十二响」由 nnn 个子程序构成,第 iii 个子程序所需的内存空间是 MiM_iMi。这 nnn 个子程序之间的调用关系构成了一棵以第 111 个子程序为根的树,其中第 iii 个子程序在调用树上的父亲是第 fif_ifi 个子程序。 由于内存紧张,电力控制芯片上提供了一种内存分段机制。你可以将内存分为若干个段 S1,S2,…,Sk,并将每个程序预先分配到一个固定的段。如果两个子程序没有直接或间接的调用关系,则他们可以被分配到同一个段中,反之则不能。换言之,当且仅当 aaa 和 bbb 在调用树上不是祖先-后代关系,aaa 和 bbb 可以被分配到同一个段中。 一个段的大小应当是所有分配到这个段的子程序所需内存大小的最大值,所有段大小的和不能超过系统的内存大小。 现在艾莉芬想要知道,电力控制芯片至少要有多少内存,才能保证春节十二响的正确运行。即:最少需要多大的内存,才能通过先将内存分成若干个段,再把每个子程序分配到一个段中,使得每个段中分配的所有子程序之间不存在祖先-后代关系

Input

从标准输入读入数据。
第一行包含一个正整数 nnn 表示子程序的个数,其中 n≤2×105n\le 2\times 10^5n≤2×105。
第二行有 nnn 个用空格隔开的正整数 M1,M2,…,Mn,MiM_iMi 表示第 iii 个子程序所需的内存空间。
第三行有 n−1n-1n−1 个用空格隔开的正整数 f2,f3,…,fn,满足 fi<if_i<i< span="">fi<i,表示第 iii 个子程序在调用树上的父亲是第 fif_ifi 个子程序。

Output

输出到标准输出。
仅一个整数,表示最小的内存需求。

Sample Input

5
10 20 20 30 30
1 1 2 2

 Sample Output

60

Solution

启发式合并堆。

Code

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define M 200001
struct graph{
	int tot,head[M];
	struct edge{
		int next;
		int to,dis;
	}ed[M];
	void addEdge(int from,int to,int dis){
		ed[++tot].next=head[from];
		ed[tot].to=to,ed[tot].dis=dis;
		head[from]=tot;
	}
	void init(){
		tot=0;
		memset(ed,-1,sizeof(ed));
		memset(head,-1,sizeof(head));
	}
}l;
priority_queue<int>q[M];
int tmp[M],a[M],n,m,f;
void dfs(int v){
	for(int i=l.head[v];i;i=l.ed[i].next){
		int u=l.ed[i].to;
		dfs(u);
		if(q[v].size()<q[u].size())swap(q[u],q[v]);
		while(!q[u].empty()){
			tmp[++tmp[0]]=max(q[v].top(),q[u].top());
			q[v].pop(),q[u].pop();
		}
		while(tmp[0])q[v].push(tmp[tmp[0]--]);
	}
	q[v].push(a[v]);
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=2;i<=n;i++)cin>>f,l.addEdge(f,i,-1);
	dfs(1);
	long long ans=0;
	while(!q[1].empty())ans+=q[1].top(),q[1].pop();
	cout<<ans;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值