似乎这题主流做法是树剖 但是树剖怎么做啊 线段树合并我还没怎么学过 所以用线段树合并来做了
首先对于每个操作肯定是差分来维护是最方便的
每个点我们建立一颗权值线段树 对于x y z 操作
分别在树x,树y,树lca(x,y),树 fa[lca(x,y)] 上的z位置进行+1,+1,-1,-1的操作 这是典型的树上点差分
然后我们由下而上的统计每棵树的答案就行了
据说这种做法理论上只有nlogn的复杂的 不过常数巨大 可以比 nlognlogn的做法还慢
一开始卡了两个点 吸氧能过 后来优化了两个常数 快读和求lca的常数(预处理logx) 总算是卡过了
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
#define mid (l+r>>1)
int fa[N][23],dep[N],rt[N],ans[N],lg[N];
int h[N],to[N<<1],nex[N<<1],cur;
inline int read(){
int x = 0,w = 0;char c = 0;
while(c<'0'||c>'9') w|=c=='-',c=getchar();
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return w?-x:x;
}
void add_edge(int x,int y){
to[++cur]=y;nex[cur]=h[x];h[x]=cur;
}
struct segment_tree{
int mxv[N*50],mxp[N*50],L[N*50],R[N*50],tot;
void pushup(int id){
if(mxv[L[id]]>=mxv[R[id]]) mxv[id]=mxv[L[id]],mxp[id]=mxp[L[id]];
else mxv[id]=mxv[R[id]],mxp[id]=mxp[R[id]];
return;
}
void update(int &id,int l,int r,int pos,int val){
if(!id) id=++tot;
if(l==r){
mxv[id]+=val,mxp[id]=l;return;
}
if(pos<=mid) update(L[id],l,mid,pos,val);
else update(R[id],mid+1,r,pos,val);
pushup(id);
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x+y;
if(l==r){
mxv[x]+=mxv[y],mxp[x]=l;return x;
}
L[x]=merge(L[x],L[y],l,mid);
R[x]=merge(R[x],R[y],mid+1,r);
pushup(x);
return x;
}
}tr;
void dfs1(int u,int fath){
fa[u][0]=fath;dep[u]=dep[fath]+1;
for(int i = 1; i <= lg[dep[u]]; i++) fa[u][i]=fa[fa[u][i-1]][i-1];
for(int j = h[u]; j; j=nex[j]) if(to[j]!=fath) dfs1(to[j],u);
}
void dfs2(int u){
for(int i = h[u]; i; i = nex[i]){
if(to[i]!=fa[u][0]){
dfs2(to[i]);
rt[u]=tr.merge(rt[u],rt[to[i]],1,1e5);
}
}
if(tr.mxv[rt[u]]==0) ans[u]=0;
else ans[u]=tr.mxp[rt[u]];
}
int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
while(dep[x]>dep[y]) x=fa[x][lg[dep[x]-dep[y]]-1];
if(x==y) return x;
for(int i = lg[dep[x]-1]; i >= 0; i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) lg[i]=lg[i-1]+(1<<lg[i-1]==i);
for(int i = 1; i <= n-1; i++){
int u,v;
u=read(),v=read();
add_edge(u,v);
add_edge(v,u);
}
dfs1(1,0);
for(int i = 1; i <= m; i++){
int x,y,z;
x=read(),y=read(),z=read();
int lc=lca(x,y);
tr.update(rt[x],1,1e5,z,1);
tr.update(rt[y],1,1e5,z,1);
tr.update(rt[lc],1,1e5,z,-1);
if(fa[lc][0]) tr.update(rt[fa[lc][0]],1,1e5,z,-1);
}
dfs2(1);
for(int i = 1; i <= n; i++) printf("%d\n",ans[i]);
return 0;
}