首先村落里的一共有n座房屋,并形成一个树状结构。然后救济粮分m次发放,每次选择两个房屋(x,y),然后对于x
到y的路径上(含x和y)每座房子里发放一袋z类型的救济粮。然后深绘里想知道,当所有的救济粮发放完毕后,每
座房子里存放的最多的是哪种救济粮。
1 <= n, m <= 100000, 1 <= a, b, x, y <= n, 1 <= z <= 100000
//针对每个给出的树上的点,建立一个权值线段树,动态开点
//权值线段树的叶子点,代表这个树上的点所存放的东西,及数量
#include<bits/stdc++.h>
#define mid ((l+r)>>1)
using namespace std;
const int N=100000+2;
const int U=100001;
int n,m;
struct haha
{
int nxt,to;
}e[2*N];
int hd[N],cnt;
void add(int x,int y)
{
e[++cnt].nxt=hd[x];
e[cnt].to=y;
hd[x]=cnt;
}
int fa[N][18];
int dep[N];
int ans[N];
void dfs(int x,int d)
{
dep[x]=d;//x的深度为d,根结点深度为1
for(int i=hd[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(y==fa[x][0])
continue;
fa[y][0]=x;
dfs(y,d+1);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
for(int j=17;j>=0;j--)
{
if(dep[fa[x][j]]>=dep[y]) x=fa[x][j];
}
if(x==y) return x;
for(int j=17;j>=0;j--)
{
if(fa[x][j]!=fa[y][j]) x=fa[x][j],y=fa[y][j];
}
return fa[x][0];
}
struct node
{
int mx,id;
int ls,rs;
}t[N*60];
int tot;
int rt[N];
void pushup(int x)//上传标记
//mx最多数字的个数
//id最多数字是哪一种
{
if(t[x].ls&&t[x].rs)//如果有左右结点
{
t[x].mx=max(t[t[x].ls].mx,t[t[x].rs].mx);
t[x].id=t[t[x].ls].mx>=t[t[x].rs].mx?t[t[x].ls].id:t[t[x].rs].id;
}
else
if(t[x].ls)
{
t[x].mx=t[t[x].ls].mx;
t[x].id=t[t[x].ls].id;
}
else
if(t[x].rs)
{
t[x].mx=t[t[x].rs].mx;
t[x].id=t[t[x].rs].id;
}
}
void upda(int &x,int l,int r,int p,int c)
//upda(rt[x],1,U,z,1);
//x代表结点编号,l,r代表范围
//p代表加入哪一种货物
//c代表所加的数量
{
if(!x)
x=++tot;
if(l==r)
{
t[x].id=l; //在线段树中编号为x的结点,所存放食品的种类
t[x].mx+=c;//存放食品的数量
return;
}
if(p<=mid) //转到左子树更新
upda(t[x].ls,l,mid,p,c);
else //转到右子树更新
upda(t[x].rs,mid+1,r,p,c);
pushup(x);
}
int merge(int x,int y,int l,int r)
{
if(!x||!y)
//哪个点不为0就返回哪个点的编号,如果同时为0就返回0
//如果此处没有返回,则说明合并的结点不为空
return x|y;
if(l==r)//到了叶子点,强行合并
{
t[x].mx+=t[y].mx;
}
else
{
t[x].ls=merge(t[x].ls,t[y].ls,l,mid);
//左子树与左子树合并,返回得是结点的编号
t[x].rs=merge(t[x].rs,t[y].rs,mid+1,r);
//右子树与右子树合并
pushup(x);//标记上传
}
return x;
}
void sol(int x)
//求出x点存放的物品,哪种编号的最多
{
for(int i=hd[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(y==fa[x][0]) continue;
sol(y);
rt[x]=merge(rt[x],rt[y],1,U);//与其子结点进行合并
}
if(t[rt[x]].mx>0)
ans[x]=t[rt[x]].id;
}
int main()
{
scanf("%d%d",&n,&m);int x,y;
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1,1);
dep[0]=-1;
for(int j=1;j<=17;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
int z;
while(m--)
{
scanf("%d%d%d",&x,&y,&z);
int anc=lca(x,y);
upda(rt[x],1,U,z,1); //对x这个端点,加1
upda(rt[y],1,U,z,1);//对y这个端点,加1
upda(rt[anc],1,U,z,-1);//对lca减1
if(fa[anc][0]) //如果lca有父亲点,也要减1
upda(rt[fa[anc][0]],1,U,z,-1);
}
sol(1);
for(int i=1;i<=n;i++)
{
printf("%d
",ans[i]);
}
return 0;
}