병용 세그먼트 트리, 각 노드는 트리 선 두께를 유지, 구호 식품 카테고리, 구호 곡물 번호 (첨자)의 유지 보수 간격의 가장 큰 수의 인덱스입니다. 각각의 노드와 응답이 \ (트레 [ROT는 [X 방향] \) .
그리고 유통 경로, 차동 사고 트리 포인트를 적용 \ (U, V \) , 우리는 \ (U \) 에 +1 (V \) \ 1에서 \ (LCA (U, V) \ ) -1에서 상기 \ (FA (LCA) \) -1과 바닥 프리픽스 트리 현재 노드 정보 가입 최종 수의 세그먼트를 병합 한 트리를 만들었다.
합병 할 때 발생할 수있는 주 \ (트레는 [ROT [X]를 ] \) 되지 않는다 (0 \)를 \ 있지만 \ (합계 [ROT [X] ] \) 된다 \ (0 \) 케이스 그 번호는 현재 \는 (트레 [ROT [X]를 ] \) 개수 릴리프 음식 \ (0 \) ,이 경우, 그렇게하는 것은한다 \ (ANS는 [X] \) 가 업데이트된다 (0 \) \ (항 ) 질문의 의미.
#include <cstdio>
#include <algorithm>
#define MAXN 100001
#define LOG 19
#define mxr 100000
using namespace std;
inline int read(){
char ch=getchar();int s=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') s=s*10+(ch^'0'),ch=getchar();
return s;
}
int head[MAXN],nxt[MAXN*2],vv[MAXN*2],tot;
inline void add_edge(int u, int v){
vv[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
int n,m;
#define MAXM MAXN*20
int tre[MAXM],sum[MAXM],sl[MAXM],sr[MAXM],cnt;
void push_up(int x){
if(sl[x]==0){
sum[x]=sum[sr[x]];
tre[x]=tre[sr[x]];
return;
}
if(sr[x]==0){
sum[x]=sum[sl[x]];
tre[x]=tre[sl[x]];
return;
}
if(sum[sl[x]]>=sum[sr[x]]){
sum[x]=sum[sl[x]];
tre[x]=tre[sl[x]];
}else{
sum[x]=sum[sr[x]];
tre[x]=tre[sr[x]];
}
}
void change(int &x, int l, int r, int pos, int val){
if(x==0) x=++cnt;
if(l==r){
sum[x]+=val;
tre[x]=pos;
return;
}
int mid=(l+r)>>1;
if(pos<=mid) change(sl[x], l, mid, pos, val);
else change(sr[x], mid+1, r, pos, val);
push_up(x);
}
int merge(int a, int b, int l, int r){
if(a==0||b==0) return a+b;
if(l==r){
sum[a]+=sum[b];
return a;
}
int mid=(l+r)>>1;
sl[a]=merge(sl[a], sl[b], l, mid);
sr[a]=merge(sr[a], sr[b], mid+1, r);
push_up(a);
return a;
}
int f[MAXN][LOG],dep[MAXN];
void dfs(int u, int fa){
f[u][0]=fa;
dep[u]=dep[fa]+1;
for(int i=1;i<LOG;++i)
f[u][i]=f[f[u][i-1]][i-1];
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==fa) continue;
dfs(v, u);
}
}
int lca(int a, int b){
if(dep[a]<dep[b]) swap(a, b);
for(int i=LOG-1;i>=0;--i)
if(dep[f[a][i]]>=dep[b])
a=f[a][i];
if(a==b) return a;
for(int i=LOG-1;i>=0;--i)
if(f[a][i]!=f[b][i])
a=f[a][i],b=f[b][i];
return f[a][0];
}
int rot[MAXN],ans[MAXN];
void calc(int u, int fa){
for(int i=head[u];i;i=nxt[i]){
int v=vv[i];
if(v==fa) continue;
calc(v, u);
rot[u]=merge(rot[u], rot[v], 1, mxr);
}
ans[u]=tre[rot[u]];
if(sum[rot[u]]==0) ans[u]=0; // 特判没有救济粮的情况
}
int main(){
n=read(),m=read();
for(int i=1;i<n;++i){
int a=read(),b=read();
add_edge(a, b);
add_edge(b, a);
}
dfs(1, 0);
for(int i=1;i<=m;++i){
int a=read(),b=read(),x=read();
int l=lca(a, b);
change(rot[a], 1, mxr, x, 1);
change(rot[b], 1, mxr, x, 1);
change(rot[l], 1, mxr, x, -1);
change(rot[f[l][0]], 1, mxr, x, -1);
}
calc(1, 0);
for(int i=1;i<=n;++i) printf("%d\n", ans[i]);
return 0;
}