60分求助(数列剖分)
查看原帖
60分求助(数列剖分)
841182
XiangXunYi楼主2024/8/19 22:02
#include <stdio.h>
#include <vector>
#include <set>
using namespace std;
int n, m, k[300005];
struct work
{
	int u, v;
	long long len;
}works[300005];
struct pii
{
	int x;
	long long y;
};
vector<pii> g[300005], maxa[300005];
void add(int l, int r, long long k)
{
	if (l > r)
		return;
	maxa[l].push_back({ 1, k });
	maxa[r + 1].push_back({ 0, k });
}
namespace cuttruee
{
	int siz[300005], hson[300005], father[300005], deep[300005], dfn[300005], dcnt, top[300005];
	void dfs1(int u, int fa, int dp)
	{
		deep[u] = dp;
		siz[u] = 1;
		father[u] = fa;
		for (auto [v, k] : g[u])
			if (v != fa)
			{
				dfs1(v, u, dp + 1);
				siz[u] += siz[v];
				if (siz[v] > siz[hson[u]])
					hson[u] = v;
			}
	}
	void dfs2(int u, int tp)
	{
		dfn[u] = ++dcnt;
		top[u] = tp;
		if (hson[u] != 0)
			dfs2(hson[u], tp);
		for (auto [v, k] : g[u])
			if (v != father[u] && v != hson[u])
				dfs2(v, v);
	}
	void update(int u, int v, long long k)
	{
		while (top[u] != top[v])
		{
			if (deep[top[u]] < deep[top[v]])
				u ^= v ^= u ^= v;
			add(dfn[top[u]], dfn[u], k);
			u = father[top[u]];
		}
		if (deep[u] < deep[v])
			u ^= v ^= u ^= v;
		add(dfn[v] + 1, dfn[u], k);
	}
	int lca(int u, int v)
	{
		while (top[u] != top[v])
		{
			if (deep[top[u]] < deep[top[v]])
				u ^= v ^= u ^= v;
			u = father[top[u]];
		}
		if (deep[u] < deep[v])
			u ^= v ^= u ^= v;
		return v;
	}
}
long long sum[300005];
void dfs(int u, int fa, long long sum)
{
	sum += k[u];
	::sum[u] = sum;
	for (auto [v, k] : g[u])
		if (v != fa)
		{
			::k[v] = k;
			dfs(v, u, sum);
		}
}
multiset<long long> st;
bool check(long long x)
{
	for (int i = 1; i <= n; ++i)
		maxa[i].clear();
	int cnt = 0;
	for (int i = 1; i <= m; ++i)
		if (works[i].len > x)
		{
			cuttruee::update(works[i].u, works[i].v, works[i].len - x);
			++cnt;
		}
	st.clear();
	st.insert(0);
	for (int i = 1; i <= n; ++i)
	{
		for (auto [opt, k] : maxa[i])
			if (opt == 0)
				st.erase(st.lower_bound(k));
			else
				st.insert(k);
		if (st.size() == cnt + 1 && *st.rbegin() <= k[i])
			return true;
	}
	return false;
}
int main()
{
	scanf("%d%d", &n, &m);
	for (int i = 1, u, v, k; i < n; ++i)
	{
		scanf("%d%d%d", &u, &v, &k);
		g[u].push_back({ v, k });
		g[v].push_back({ u, k });
	}
	dfs(1, -1, 0);
	cuttruee::dfs1(1, -1, 0);
	cuttruee::dfs2(1, 1);
	for (int i = 1, u, v; i <= m; ++i)
	{
		scanf("%d%d", &u, &v);
		works[i] = { u, v, sum[u] + sum[v] - (sum[cuttruee::lca(u, v)] << 1) };
	}
	long long l = 0, r = 1e18;
	while (l < r)
	{
		long long mid = (l + r) >> 1;
		if (check(mid))
			r = mid;
		else
			l = mid + 1;
	}
	printf("%lld\n", l);
	return 0;
}

记录

2024/8/19 22:02
加载中...