Jan. 10th 2026

Relief Grain

建模成线性差分,讨论此时的解法:类似于扫描线,将一个区间用两个点表示
[L, R] \(\to\) L + 1, R - 1

用一个 events 数组存储:

struct RRC{
	int value;
	int type;
};

vector<RRC> events[maxn];

对于一个区间 [L, R]

events[L].push_back((RRC){delta, 1});
events[R - 1].push_back((RRC){delta, -1});

而节点信息可以使用 set 来存储 :

struct node{
	int value;
	int times;
	bool operator<(const node &another) const{
		if (this->times == another.times) return this->value < another.value;
		return this->times > another.times;
	}
};

set<node> S;

void update(int value, int type) {
	auto it = S.find({value, bucket[value]});
	if (it != S.end()) S.erase(it);
	bucket[value] += type;
	if (bucket[value] > 0) S.insert({value, bucket[value]});
}

然后就可以使用树链剖分,将树上问题转换成区间问题:

void chain_update(int x, int y, int delta) {
	while (top[x] != top[y]) {
		if (depth[top[x]] < depth[top[y]]) swap(x, y);
		events[dfn[top[x]]].push_back((RRC){delta, 1});
		events[dfn[x] + 1].push_back((RRC){delta, -1});
		x = father[top[x]];
	}

	if (depth[x] > depth[y]) swap(x, y);
	events[dfn[x]].push_back((RRC){delta, 1});
	events[dfn[y] + 1].push_back((RRC){delta, -1});
}

Cold ~~~~ :

View Code
#include<bits/stdc++.h>
using namespace std;

using lf = double;
using ll = long long;
using ull = unsigned long long;

const int maxn = 1e5 + 5;

int wealth[maxn];
int n, m, root = 1, p; // about the question

namespace TREE_CHAIN {

	vector<int> adj[maxn];
	int depth[maxn], father[maxn], size[maxn];

	int dfn[maxn], out[maxn], dfs[maxn], cnt;

	int heavy_son[maxn], top[maxn]; // tree chain

	int bucket[maxn]; // bucket

	struct node{
		int value;
		int times;
		bool operator<(const node &another) const{
			if (this->times == another.times) return this->value < another.value;
			return this->times > another.times;
		}
	};

	set<node> S;

	void update(int value, int type) {
		auto it = S.find({value, bucket[value]});
		if (it != S.end()) S.erase(it);
		bucket[value] += type;
		if (bucket[value] > 0) S.insert({value, bucket[value]});
	}

	void init(int u, int fath, int dep) {
		size[u] = 1;
		father[u] = fath;
		depth[u] = dep;
		for (int v : adj[u]) {
			if (v == fath) continue;
			init(v, u, dep + 1);
			size[u] += size[v];
			if (size[v] > size[heavy_son[u]]) heavy_son[u] = v;
		}
	}
	
	void another_init(int u, int fath, int head) {
		top[u] = head;
		dfn[u] = ++cnt;
		dfs[cnt] = u;
		if (heavy_son[u]) another_init(heavy_son[u], u, head);
		for (int v : adj[u]) {
			if (v == fath or v == heavy_son[u]) continue;
			another_init(v, u, v);
		}
		out[u] = cnt;
	}
	
	struct RRC{
		int value;
		int type;
	};
	
	vector<RRC> events[maxn];
	
	void chain_update(int x, int y, int delta) {
		while (top[x] != top[y]) {
			if (depth[top[x]] < depth[top[y]]) swap(x, y);
			events[dfn[top[x]]].push_back((RRC){delta, 1});
			events[dfn[x] + 1].push_back((RRC){delta, -1});
			x = father[top[x]];
		}
		
		if (depth[x] > depth[y]) swap(x, y);
		events[dfn[x]].push_back((RRC){delta, 1});
		events[dfn[y] + 1].push_back((RRC){delta, -1});
	}
	
	void all_init() {
		cnt = 0;
		memset(depth, 0, sizeof(depth));
		memset(father, 0, sizeof(father));
		memset(size, 0, sizeof(size));
		memset(dfn, 0, sizeof(dfn));
		memset(out, 0, sizeof(out));
		memset(dfs, 0, sizeof(dfs));
		memset(heavy_son, 0, sizeof(heavy_son));
		memset(top, 0, sizeof(top));
		memset(bucket, 0, sizeof(bucket));
		S.clear();
		for (int i = 0; i < maxn; i++) {
			adj[i].clear();
			events[i].clear();
		}
	}
}

using namespace TREE_CHAIN;

int ans[maxn];

void solve() {
	all_init();
//	cin >> n >> m >> root >> p;
	
	if (n == m and !n) exit(0);
	
	for (int i = 1; i < n; i++) {
		int u, v;
		cin >> u >> v;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	
	init(root, 0, 1);
	another_init(root, 0, root);
	
	for (int i = 1; i <= m; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		chain_update(u, v, w);
	}
	
	for (int i = 1; i <= n; i++) {
//		S.clear();
		for (RRC event : events[i])
			update(event.value, event.type);
		ans[dfs[i]] = S.begin()->value;
	}
	
	for (int i = 1; i <= n; i++) cout << ans[i] << "\n";
	
}

int main() {
	
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cout.tie(nullptr);
	
	int T = 1;
	//	cin >> T;
	while (cin >> n >> m) solve();
	
	return 0;
}
posted @ 2026-01-10 11:26  Yangyihao  阅读(3)  评论(0)    收藏  举报