列表

详情


NC247580. 牛牛的考试

描述

最近正值期末考试,牛牛看了看自己的考试安排,还有 n 门课程都需要预习,每个课程有对应的预习时长,并且这些课程之间一共存在 n-1 对先后关系,即只有预习完了 a 课程才能预习 b 课程。(第 1 个课程是最难的,需要预习完其他所有课程才能预习。)但是聪明的牛牛可以选择双开学习,手机和电脑在同一时间预习不同的课程,也可以选择单开,某个时间只预习一个课程。每个课程预习后,牛牛就会不间断的继续预习下一个能预习的课程。问牛牛最短多久能预习完所有课程?
牛牛在预习某个课程时,不要求一口气预习完该课程,例如某个课程需要花费 5 分钟,牛牛可以选择先预习 2 分钟,然后去预习别的课程,再回来预习剩下的 3 分钟。

输入描述

第一行输入一个正整数  ,表示牛牛需要预习的课程数量。这些课程的编号为 
第二行输入 n 个正整数 a_1,a_2,...a_n ,分别代表第 i 个课程需要花费 分钟预习完。
第三行输入 n-1 个正整数 ,代表预习完第 个课程才能预习第 个课程。

输出描述

输出一行一个整数,代表牛牛预习完这 n 个课程最少需要多少分钟。

示例1

输入:

9
3 3 2 3 4 5 3 6 3
1 1 2 2 2 3 3 7

输出:

18

说明:

样例里的课程间先后关系如图所示,只有预习完了 4,5,6 三门课程才能预习 2 号课程。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++ 11.0.1) 解法, 执行用时: 86ms, 内存消耗: 34076K, 提交时间: 2023-01-07 12:17:47

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
const int mod =100000007;
ll a[N],dp[N],g[N],n;
vector<int>ve[N];
void dfs(int x){
	for(auto i:ve[x]){
		dfs(i);
		dp[x]=max(dp[x],dp[i]);
		g[x]+=g[i];
	}
	dp[x]=a[x]+max(dp[x],(g[x]+1)/2);
	g[x]+=a[x];
}
int main()
{
	std::ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i];
	for(int i=2;i<=n;i++){
		int k;
		cin>>k;
		ve[k].push_back(i);
	}
	dfs(1);
	cout<<dp[1]<<endl;
	return 0;
}

C++(g++ 7.5.0) 解法, 执行用时: 74ms, 内存消耗: 35776K, 提交时间: 2023-01-06 21:25:22

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll i,j,k,n,m,t,a[1005000],res,f[1005000],g[1005000];
vector<int> v[1005000];

void dfs(int x){
	for(auto i:v[x]){
		dfs(i);
		f[x]=max(f[x],f[i]);
		g[x]+=g[i];
	}
	f[x]=a[x]+max(f[x],(g[x]+1)/2);
	g[x]+=a[x];
}

int main() {
	ios::sync_with_stdio(0);cin.tie(0);
	cin>>n;
	for(i=1;i<=n;i++){
		cin>>a[i];
	}
	for(i=2;i<=n;i++){
		cin>>k;v[k].push_back(i);
	}
	dfs(1);
	cout<<f[1];
}

上一题