G. Vlad and the Mountains

G. Vlad and the Mountains

https://codeforces.com/contest/1851/problem/G

离线+并查集

首先观察路径 ijk 其必须满足如下条件:

  • hjhie
  • hkhjehj+hihkhie

不难发现我们的路径最后的变化量只和起点和终点的高度有关。

那么要以 e 为能量初值,从 ab 的一条合法的路径,必然满足经过的所有点 k 都满足 hkha+e

容易想到考虑点权的并查集的 trick,想到离线处理,把询问按 ha+e 和 点权 hi 都从小到大排,每次加入一个满足 hiha+e 的点,合并所有和 i 相邻且已经加入的点的边。当 a,b 位于同一个连通块的时候,就一定存在一个满足条件的合法的路径从 ab

Code

#include <bits/stdc++.h>

using LL = long long;

void solve() {
	int n, m;
	std::cin >> n >> m;
	std::vector<std::vector<int>> g(n + 1);
	std::vector<std::array<int, 2>> p(n + 1);
	for (int i = 1; i <= n; i++) {
		std::cin >> p[i][0];
		p[i][1] = i;
	}
	while (m--) {
		int u, v;
		std::cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	int q;
	std::cin >> q;
	std::vector<std::array<int, 4>> qry(q + 1);
	std::vector<int> ans(q + 1);
	for (int i = 1; i <= q; i++) {
		int a, b, e;
		std::cin >> a >> b >> e;
		qry[i][0] = p[a][0] + e, qry[i][1] = a, qry[i][2] = b, qry[i][3] = i;
	}
	std::sort(qry.begin() + 1, qry.end());
	std::sort(p.begin() + 1, p.end());
	std::vector<int> f(n + 1);
	for (int i = 1; i <= n; i++) {
		f[i] = i;
	}
	std::function<int(int)> find = [&](int x) -> int {
		return x == f[x] ? x : f[x] = find(f[x]);
	};
	std::vector<bool> st(n + 1, false);
	auto add = [&](int u) {
		st[u] = true;
		for (auto v : g[u]) {
			if (st[v]) {
				f[find(v)] = find(u);
			}
		}
	};
	for (int i = 1, j = 1; i <= q; i++) {
		while (j <= n && p[j][0] <= qry[i][0]) {
			add(p[j++][1]);
		}
		ans[qry[i][3]] = find(qry[i][1]) == find(qry[i][2]);
	}	
	for (int i = 1; i <= q; i++) {
		std::cout << (ans[i] ? "YES" : "NO") << '\n';
	}
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    std::cin >> t;
    while (t--) {
    	solve();
    }


    return 0;
}
posted @   jackle  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示