Luogu P4556 [Vani有约会]雨天的尾巴
Link
树上差分+线段树合并。
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
const int N=100007,M=N*40,lim=100000;
int cnt,fa[N],dep[N],size[N],son[N],top[N],ans[N],ch[M][2];
struct pi{int fi,se;}t[M];
std::vector<int>e[N];std::vector<pi>vec[N];
int operator<(const pi&a,const pi&b){return a.se<b.se||(a.se==b.se&&a.fi>b.fi);}
pi operator+(const pi&a,const pi&b){return {a.fi,a.se+b.se};}
int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
int lca(int u,int v){for(;top[u]^top[v];u=fa[top[u]])if(dep[top[u]]<dep[top[v]])std::swap(u,v);return dep[u]<dep[v]? u:v;}
#define mid ((l+r)>>1)
void update(int p,int l,int r,pi x)
{
if(l+1==r) return t[p]=x+t[p],void();
x.fi<=mid? update(ch[p][0]? ch[p][0]:ch[p][0]=++cnt,l,mid,x):update(ch[p][1]? ch[p][1]:ch[p][1]=++cnt,mid,r,x);
t[p]=std::max(t[ch[p][0]],t[ch[p][1]]);
}
void merge(int u,int v,int l,int r)
{
if(l+1==r) return t[u]=t[u]+t[v],void();
if(ch[u][0]&&ch[v][0]) merge(ch[u][0],ch[v][0],l,mid); else if(ch[v][0]) ch[u][0]=ch[v][0];
if(ch[u][1]&&ch[v][1]) merge(ch[u][1],ch[v][1],mid,r); else if(ch[v][1]) ch[u][1]=ch[v][1];
t[u]=std::max(t[ch[u][0]],t[ch[u][1]]);
}
#undef mid
void dfs1(int u,int f)
{
dep[u]=dep[fa[u]=f]+1,size[u]=1;
for(int v:e[u]) if(v^f) if(dfs1(v,u),size[u]+=size[v],size[v]>size[son[u]]) son[u]=v;
}
void dfs2(int u,int t)
{
top[u]=t;
if(son[u]) dfs2(son[u],t);
for(int v:e[u]) if(v^son[u]&&v^fa[u]) dfs2(v,v);
}
void dfs3(int u)
{
for(int v:e[u]) if(v^fa[u]) dfs3(v),merge(u,v,0,lim);
auto it=vec[u].begin();
for(auto it:vec[u])
update(u,0,lim,it);
ans[u]=t[u].fi;
}
int main()
{
int n=read(),m=read();cnt=n;
for(int i=1,u,v;i<n;++i) u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
dfs1(1,0),dfs2(1,1);
for(int i=1,u,v,w,p;i<=m;++i) u=read(),v=read(),w=read(),p=lca(u,v),vec[u].push_back({w,1}),vec[v].push_back({w,1}),vec[p].push_back({w,-1}),vec[fa[p]].push_back({w,-1});
dfs3(1);
for(int i=1;i<=n;++i) printf("%d\n",ans[i]);
}