栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > C/C++/C#

CodeForces 1714G Path Prefixes

C/C++/C# 更新时间:发布时间: 百科书网 趣学号

原题链接:https://codeforces.com/contest/1714/problem/G

题意: 给你一棵有根的树。它包含 n 个顶点,从 1 到 n 编号。根是顶点 1。每条边都有两个权值A[i],B[i],从1开始到点 u (2 ≤ u ≤ n)路径中的所有边的权重A[i]之和 >= 从1开始到点 v (2 ≤ v ≤ u)路径中的所有边的权重B[i]之和,求出每一个点u对应v的最大深度

 

 

思路:首先所有的权重B[i]都是正的,所以前缀上的量是单调递增的。那么就可以使用二分搜索来寻找顶点的答案。那么剩下的就简单了,我们只需要快速找到路径前缀上的权重B[i]的和。如何记录呢?经过思考完全可以用深度优先搜索找到当前的路径的前缀和,并将当前路径的前缀总和存储在堆栈中:转到顶点,将总和添加到路径的末尾,以防万一在退出时将其删除。

AC代码:

#include 
typedef long long ll;

void solve() {
	int n;
	std::cin >> n;
	std::vector>>a(n);
	for (int i = 1; i < n; i++) {
		int p, x, y;
		std::cin >> p >> x >> y;
		p--;
		a[p].push_back({i, x, y});
	}
	std::vectorans(n);

	std::vectorA(n), B(n), s;
	std::function dfs = [&](int u) {
		s.push_back(B[u]);
		if (u > 0) {
			ans[u] = std::upper_bound(s.begin(), s.end(), A[u]) - s.begin() - 1;
		}
		for (auto [v, x, y] : a[u]) {
			A[v] = A[u] + x;
			B[v] = B[u] + y;
			dfs(v);
		}
		s.pop_back();
	};
	dfs(0);
	for (int i = 1; i < n; i++) std::cout << ans[i] << " n"[i==n-1];
}

int main() {
	std::ios_base::sync_with_stdio(false);
	std::cin.tie(nullptr);
	int T;
	std::cin >> T;
	while (T--) {
		solve();
	}
    return 0;
}

转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/1033532.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号