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;
}

浙公网安备 33010602011771号