rt,快红温了/oh
可以不用在意注释。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 6e6 + 10;
const int M = 1e5 + 10;
int n, m;
namespace ra
{
int head[M << 1], ne[M << 1], to[M << 1], id;
inline int read()
{
int s = 0, w = 1;
char ch = getchar();
while(ch < '0' || ch > '9')
{
if(ch == '-') w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9')
{
s = (s << 3) + (s << 1) + (ch ^ 48);
ch = getchar();
}
return s * w;
}
void add(int x, int y)
{
to[++id] = y, ne[id] = head[x], head[x] = id;
}
//可爱快读建边
}
using namespace ra;
namespace LCA
{
int fa[M], dep[M], son[M], siz[M];
void dfs1(int u, int faa)
{
fa[u] = faa;
dep[u] = dep[faa] + 1;
siz[u] = 1;
for(int i = head[u]; i; i = ne[i])
{
int v = to[i];
if(v == faa) continue;
dfs1(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
int top[M];
// int dfn[M], dn;
void dfs2(int u, int tp)
{
top[u] = tp;
// dfn[u] = ++dn;
if(!son[u]) return ;
dfs2(son[u], tp);
for(int i = head[u]; i; i = ne[i])
{
int v = to[i];
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
int LCA(int x, int y)
{
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x, y);
x = fa[top[x]];
}
return (dep[x] < dep[y] ? x : y);
}
//可爱树剖LCA
}
using namespace LCA;
namespace segment_tree
{
int ck = 0;
/*
cnt:众数出现次数
num:众数(是哪个)
ch[0/1]:左右儿子
ck:新点编号
*/
int cnt[N], num[N];
int ch[N][3];
void push_up(int u)
{
if(cnt[ch[u][0]] >= cnt[ch[u][1]]) cnt[u] = cnt[ch[u][0]], num[u] = num[ch[u][0]];
else cnt[u] = cnt[ch[u][1]], num[u] = num[ch[u][1]];
/*
看左右儿子哪个众数更众数
更新 次数 和 众数
*/
}
int change(int u, int l, int r, int x, int v)
{
if(!u) u = ++ck;
if(l == r)
{
cnt[u] += v;
num[u] = l;
return u;
}
int mid = (l + r) >> 1;
if(x <= mid) ch[u][0] = change(ch[u][0], l, mid, x, v);
else ch[u][1] = change(ch[u][1], mid + 1, r, x, v);
push_up(u);
return u;
/*
单点加 v
朴素递归
*/
}
int merge(int x, int y, int l, int r)
{
if(!x || !y) return x + y;
if(x == y)
{
cnt[x] += cnt[y];
num[x] = l;
return x;
//同上
}
int mid = (l + r) >> 1;
ch[x][0] = merge(ch[x][0], ch[y][0], l, mid);
ch[x][1] = merge(ch[x][1], ch[y][1], mid + 1, r);
push_up(x);
return x;
/*
把 Y 递归并到 X 上
*/
}
}
using namespace segment_tree;
int a[M], b[M], c[M], mc;//mc:max of c
int root[M], ans[M];
void dfs(int u, int fa)
{
for(int i = head[u]; i; i = ne[i])
{
int v = to[i];
if(v == fa) continue;
dfs(v, u);
root[u] = merge(root[u], root[v], 1, mc);
}
if(cnt[root[u]]) ans[u] = num[root[u]];
}
signed main()
{
n = read(), m = read();
for(int i = 1; i < n; i++)
{
int x = read(), y = read();
add(x, y);
add(y, x);
}
dfs1(1, 0);
dfs2(1, 1);
for(int i = 1; i <= m; i++)a[i] = read(), b[i] = read(), c[i] = read(), mc = max(mc, c[i]);
for(int i = 1; i <= m; i++)
{
/*
差分的把 a-b 的路径上的点++
(a-root)++, (b-root)++
(lca-root)--, (fa[lca]-root)--
*/
int lca = LCA::LCA(a[i], b[i]);
root[a[i]] = change(root[a[i]], 1, mc, c[i], 1);
root[b[i]] = change(root[b[i]], 1, mc, c[i], 1);
root[lca] = change(root[lca], 1, mc, c[i], -1);
lca = fa[lca];//变为父亲
if(!lca) continue;
root[lca] = change(root[lca], 1, mc, c[i], -1);
}
dfs(1, 0);//跑答案
for(int i = 1; i <= n; i++) printf("%lld\n", ans[i]);
return 0;
}