边权差分
将边权转化成子节点的点权,在a到b路径上边权加c等于在a和b上分别加c,在lca(a,b)上减2c,此时边权和等于子树差分和
点权差分
在a到b路径上点权加c等于在a和b上分别加c,在lca(a,b)和fa[lca(a,b)]上减c,此时点权和等于子树差分和
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int N=1e5+10;
struct node
{
int l,r,mx,sum;
}tree[100*N];
int col[N];
int h[N],nex[2*N],to[2*N],con=1,id=1,n,rt[N],par[N][20],d[N];
int ans[N],lg[N];
void add(int a,int b)
{
nex[con]=h[a];
h[a]=con;
to[con++]=b;
}
void up(int now,int ls,int rs)
{
if(tree[ls].mx==tree[rs].mx)
{
tree[now].mx=tree[ls].mx;
tree[now].sum=min(tree[ls].sum,tree[rs].sum);
}
else if(tree[ls].mx>tree[rs].mx)
{
tree[now].mx=tree[ls].mx;
tree[now].sum=tree[ls].sum;
}
else
{
tree[now].mx=tree[rs].mx;
tree[now].sum=tree[rs].sum;
}
}
void change(int l,int r,int &now,int x,int v)
{
if(!now)
{
now=id++;
// tree[now].l=tree[now].r=tree[now].mx=tree[now].sum=0;
}
if(l==r)
{
tree[now].mx+=v;
tree[now].sum=l;
return;
}
int mid=(l+r)>>1;
if(x<=mid)
change(l,mid,tree[now].l,x,v);
else
change(mid+1,r,tree[now].r,x,v);
up(now,tree[now].l,tree[now].r);
}
void add(int l,int r,int &a,int b)
{
// cout<<l<<' '<<r<<endl;
if(!a)
{
a=b;
return;
}
else if(!b)
return;
if(l==r)
{
tree[a].mx+=tree[b].mx;
tree[a].sum=l;
return;
}
int mid=(l+r)>>1;
add(l,mid,tree[a].l,tree[b].l);
add(mid+1,r,tree[a].r,tree[b].r);
up(a,tree[a].l,tree[a].r);
return;
}
void dfs(int now,int deep)
{
for(int i=1;i<=lg[deep];++i)
par[now][i]=par[par[now][i-1]][i-1];
d[now]=deep;
for(int i=h[now];i;i=nex[i])
{
if(to[i]==par[now][0])
continue;
par[to[i]][0]=now;
dfs(to[i],deep+1);
}
}
int lca(int x,int y)
{
if(d[x]<d[y])swap(x,y);
while(d[x]>d[y])
x=par[x][lg[d[x]-d[y]]];
if(x==y)
return x;
for(int i=lg[d[x]];i>=0;--i)
{
if(par[x][i]!=par[y][i])
{
x=par[x][i];
y=par[y][i];
}
}
return par[x][0];
}
void cal(int now,int fa)
{
for(int i=h[now];i;i=nex[i])
{
if(to[i]==fa)
continue;
cal(to[i],now);
add(1,N,rt[now],rt[to[i]]);
}
ans[now]=tree[rt[now]].sum;
return;
}
int main()
{
// freopen("1.txt","r",stdin);
int m;
cin>>n>>m;
for(int i=1;i<n;++i)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
lg[1]=0;
for(int i=2;i<=n;++i)
{
if((i&(i-1))==0)
lg[i]=lg[i-1]+1;
else
lg[i]=lg[i-1];
}
dfs(1,0);
for(int i=1;i<=m;++i)
{
int a,b,c;scanf("%d%d%d",&a,&b,&c);
change(1,N,rt[a],c,1);
change(1,N,rt[b],c,1);
int d=lca(a,b);
change(1,N,rt[d],c,-1);
change(1,N,rt[par[d][0]],c,-1);
}
cal(1,0);
for(int i=1;i<=n;++i)
printf("%d\n",ans[i]);
// printf("\n");
return 0;
}