Codeforces Round 800 (Div. 2) D. Fake Plastic Trees【树、贪心】

文章讨论了一种基于节点顺序的树结构问题,其中节点的父节点序号必须小于自身。处理叶子节点时,需按照特定规则调整其值,以保证从叶子到根的值递减。当叶子节点数量不足时,会将增量分配给其他节点。整个过程涉及贪心策略,以最小化操作次数。
摘要由CSDN通过智能技术生成

链接
传送门
分析
这里有个非常重要的条件,pi<i,也就是说,每个节点的父节点的序号一定比自己小,排在最后的最大的i一定是叶子。这里非常有趣,想是一片片的地摘叶子。首先对于一个叶子而言,它需要一次操作次数,由于修改的变化量必须从叶子到1是递减的,如果说这片叶子的数目不足L,就直接加到R,然后更新父节点的值,这片叶子就操作完了,可以摘掉了,如果下次检查到这片叶子,发现大于R了,必须要减少量,可以减少到零,因为所有前面,已经被处理掉的叶子,给予变化量的叶子都可以减少该在当前新的叶子上的分量,但是减少到零不是最佳的,因为这样给下一片露出的新的叶子可操作的空间就便是了,要尽可能地大一些。依次类推,在整棵树上到处摘叶子,只有严格小于新的叶子的左边界的时候才需要操作次数加一,尽可能减少增量的衰退,重复利用每一片叶子的贡献。
联想
这题后面的贪心的思想和这题有点类似。
传送门
实现

#include <bits/stdc++.h>
#define ll long long
#define ls (u << 1)
#define rs (u << 1 | 1) 
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 2e5 + 5;
int p[N], l[N], r[N];
ll a[N];
void solve() {
	int n;
	cin >> n;
	for (int i = 2; i <= n; i++) cin >> p[i];
	for (int i = 1; i <= n; i++) cin >> l[i] >> r[i], a[i] = 0;
	int ans = 0;
	for (int i = n; i >= 1; i--) {
		if (a[i] < l[i]) a[i] = r[i], ans++;
		if (a[i] > r[i]) a[i] = r[i];
		a[p[i]] += a[i];
	}
	cout << ans << '\n';
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T = 1;
	cin >> T;
	while (T--) {
		solve();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值