技能树

题目描述

“OI 的学习,理应循序渐进”。

OI 中技能的加点形如一棵以 1 1 1 为根的树形结构,每个点的父亲就是它的前置知识,比如“min25 筛”应该在“莫比乌斯反演”之后学习,“主席树”应该在“树状数组”之后学习,形式化的来说,对于树上每个节点 u u u ,必须先学前置知识,也就是它在技能树上父亲 f a ( u ) fa(u) fa(u)

学习知识的过程可能是痛苦的,也可能是愉悦的,学习 i i i 号知识需要消耗 a i a_i ai 点愉悦度,学完之后因为满满的成就感会增加 b i b_i bi 点愉悦度,注意,此处先结算 a i a_i ai 后结算 b i b_i bi ,二者并非同一时刻结算。

现在,我们已经学习完了 1 1 1 号知识点,并拥有了一个未知的初始愉悦度,因为我们不希望学习过程中出现过分痛苦的情况,所以我们想知道:至少需要多少点初始愉悦度,使得能通过合理的学习顺序学习完技能树上所有知识,并且学习过程中任意时刻愉悦度都不为负?

数据范围

n ≤ 1 0 5 , 0 ≤ a i , b i ≤ 1 0 9 n \le 10^5,0 \le a_i,b_i \le 10^9 n105,0ai,bi109

题解

可以先考虑序列上如何操作。

首先我们应该选择那些 a i ≤ b i a_i \le b_i aibi 的点,对于这些点我们应先选择 a i a_i ai 更小的。

对于那些 a i > b i a_i > b_i ai>bi 的点,可以假定 i i i j j j 更优,然后列出不等式,发现满足这个的条件是 b i > b j b_i>b_j bi>bj ,所以从 b i b_i bi 大的开始选即可。

考虑在一棵树上,因为有父亲的限制,所以不能像上述贪心,我们发现如果有一个优先级最高的点,如果它的父亲被选了,那下一个一定会选它,所以维护优先队列,每次选择优先级最高的,跟当前父亲合并即可,这个可以用并查集实现。

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=2e5+5; LL a[N],b[N];
int n,fa[N],f[N],hd[N],V[N],nx[N],t;
struct O{
	int x;
	friend bool operator < (const O& A,const O& B){
		if (b[A.x]>=a[A.x] && b[B.x]>=a[B.x])
			return a[A.x]>a[B.x];
		if (b[A.x]<a[A.x] && b[B.x]<a[B.x])
			return b[A.x]<b[B.x];
		return b[A.x]<a[A.x];
	}
};
priority_queue<O>q;
int get(int x){
	return f[x]==x?x:f[x]=get(f[x]);
}
void add(int u,int v){
	nx[++t]=hd[u];V[hd[u]=t]=v;
}
void dfs(int x,int fr){
	fa[f[x]=x]=fr;
	for (int i=hd[x];i;i=nx[i])
		if (V[i]!=fr) dfs(V[i],x);
}
int main(){
	cin>>n;
	for (int i=2;i<=n;i++)
		scanf("%lld%lld",&a[i],&b[i]),
		q.push((O){i});
	for (int x,y,i=1;i<n;i++)
		scanf("%d%d",&x,&y),
		add(x,y),add(y,x);
	dfs(1,0);int u,v;LL A,B;
	while(!q.empty()){
		u=q.top().x;q.pop();
		v=get(fa[u]);f[u]=v;
		A=max(a[v],a[v]-b[v]+a[u]);
		B=b[v]+b[u]-a[v]-a[u]+A;
		a[v]=A;b[v]=B;
	}
	printf("%lld\n",a[1]);return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python技能树是CSDN提供的一个系统化、面向实战的学习环境,旨在帮助用户从初学者成长为合格的Python工程师。技能树整理了关于Python领域的知识点,并从CSDN的海量数据中不断更新高质量内容。除了传统的阅读学习技能树还为每个知识点提供了相应的练习题,帮助用户通过练习不断提升自己的技能,直至精通。初学者可以通过学习技能树来获得CSDN的技能认证。正在学习Python的人可以尝试技能树上的练习题,以了解自己的掌握程度。而对于Python领域的专家,他们可以给CSDN提供意见,并贡献高质量的文章。Python技能树学习方式是通过阅读学习和练习题相结合。当然,随着人工智能时代的到来,越来越多的人开始学习Python,而Python技能树则提供了全面、详细的学习内容,包括Python基础、Python进阶、前端、数据库、django、flask、数据分析和机器学习等多个模块,帮助大家全面学习和了解Python语言。123 #### 引用[.reference_title] - *1* *2* [Python之深入解析Python技能树的测评分析](https://blog.csdn.net/Forever_wj/article/details/120610403)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *3* [Python技能树](https://blog.csdn.net/CSDNedu/article/details/124011216)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值