#include<bits/stdc++.h>
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
namespace xxy {
int n, m;
std::vector<std::vector<int> >G;
std::vector<int> ans;
const int R = 1e5;
namespace sp {
struct node {
int dep, top, fa, size, hson, id;
};
std::vector<node> nod;
std::vector<int> rid;
int cntid;
void dfs1(int now, int fa)
{
// cerr<<"now:"<<now<<"fa:"<<fa<<endl;
nod[now].size = 1;
nod[now].fa = fa;
nod[now].dep = nod[fa].dep + 1;
for(auto v : G[now]) {
if(v == fa)continue;
dfs1(v, now);
nod[now].size += nod[v].size;
if(nod[v].size > nod[nod[now].hson].size)nod[now].hson = v;
}
}
void dfs2(int now, int top)
{
nod[now].top = top;
nod[now].id = ++cntid;
rid[nod[now].id] = now;
if(nod[now].hson)dfs2(nod[now].hson, top);
for(auto v : G[now]) {
if(v == nod[now].fa)continue;
if(v == nod[now].hson)continue;
dfs2(v, v);
}
}
int lca(int x, int y)
{
while(nod[x].top != nod[y].top) {
if(nod[nod[x].top].dep < nod[nod[y].top].dep)std::swap(x, y);
x = nod[nod[x].top].fa;
}
return nod[x].dep < nod[y].dep ? x : y;
}
void init()
{
nod = std::vector<node>(n + 1);
rid = std::vector<int>(n + 1);
cntid = 0;
dfs1(1, 0);
// cerr<<"out dfs1"<<endl;
dfs2(1, 1);
}
}
namespace segtree {
struct node {
int v, l, r, ma;
#define ls(x) nod[x].l
#define rs(x) nod[x].r
};
std::vector<node> nod;
std::vector<int> rt;
int cntnod;
#define mid ((l+r)>>1)
void init()
{
nod.push_back({});
rt = std::vector<int>(n + 1);
cntnod = 0;
}
void update(int x)
{
assert(x < nod.size()&&ls(x)<nod.size()&&rs(x)<nod.size());
if(nod[ls(x)].v >= nod[rs(x)].v) {
nod[x].v = nod[ls(x)].v;
nod[x].ma = nod[ls(x)].ma;
} else {
nod[x].v = nod[rs(x)].v;
nod[x].ma = nod[rs(x)].ma;
}
}
void modify(int &x, int l, int r, int p, int v)
{
if(!x) {
x = ++cntnod;
nod.push_back({});
}
assert(x < nod.size());
if(l == r) {
nod[x].v += v;
nod[x].ma = p;
return;
}
if(p <= mid)modify(ls(x), l, mid, p, v);
else modify(rs(x), mid + 1, r, p, v);
update(x);
}
void merge(int &x, int y, int l, int r)
{
assert(x < nod.size() && y < nod.size());
if(!x || !y) {
x = x | y;
} else if(l == r) {
nod[x].v += nod[y].v;
} else {
merge(ls(x), ls(y), l, mid);
merge(rs(x), rs(y), mid + 1, r);
update(x);
}
}
}
void modify(int x, int y, int z)
{
int lca = sp::lca(x, y);
segtree::modify(segtree::rt[x], 1, R, z, 1);
segtree::modify(segtree::rt[y], 1, R, z, 1);
segtree::modify(segtree::rt[lca], 1, R, z, -1);
if(sp::nod[lca].fa)segtree::modify(segtree::rt[sp::nod[lca].fa], 1, R, z, -1);
}
void calc(int now, int fa)
{
for(auto v : G[now]) {
if(v == fa)continue;
calc(v, now);
segtree::merge(segtree::rt[now], segtree::rt[v], 1, R);
}
ans[now] = segtree::nod[segtree::rt[now]].ma;
if(segtree::nod[segtree::rt[now]].v == 0)ans[now] = 0;
}
signed main()
{
#ifdef LOCAL
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
cin.tie(0), cout.tie(0);
std::ios::sync_with_stdio(false);
cin >> n >> m;
G = std::vector<std::vector<int> >(n + 1);
ans = std::vector<int>(n + 1);
for(int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
// for(int i=1;i<=n;i++){
// cerr<<"i:"<<i<<"G[i].size():"<<G[i].size()<<endl;
// }
// cerr<<"out read"<<endl;
sp::init();
// cerr<<"out sp"<<endl;
segtree::init();
// cerr<<"out init"<<endl;
for(int i = 1; i <= m; i++) {
int x, y, z;
cin >> x >> y >> z;
modify(x, y, z);
}
calc(1, 0);
for(int i = 1; i <= n; i++) {
cout << ans[i] << "\n";
}
return 0;
}
}
signed main()
{
return xxy::main();
}
如上,为了防止炸空间,用的vector动态开的空间QAQ