题意:有一个
这道题也要用到树上差分的思想,但是与上一道[POJ3417] Network不一样,这次是对所有的点标记,而不是边,这就是点差分。
点差分对于每个操作
但是由于类型过多,我们在统计子树和时,朴素方法肯定会超时,这时我们就可以采用线段树合并的方式来快速得到答案,对每个点
由于要维护两个值,且题目要求输出的类型编号要最小,所以我们可以用
本代码由于常数过大,被卡到了
//luogu-O2
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
int n,m;
int head[201010],cnt,tot;
int lc[6401010],rc[6401010];//左右儿子
int fa[201010][21],dep[201010];//lca倍增
int rt[201010],ans[201010];//根,答案
pair<int,int> maxx[6401010];//线段树维护最大值
struct node
{
int next;
int to;
}e[401010];
void add(int from,int to)
{
e[++cnt].next=head[from];
e[cnt].to=to;
head[from]=cnt;
}
void dfs(int u)
{
for(int i=1;i<=20;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==fa[u][0])
continue;
fa[v][0]=u;
dep[v]=dep[u]+1;
dfs(v);
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])
swap(x,y);
for(int i=20;i>=0;i--)
if(dep[fa[x][i]]>=dep[y])
x=fa[x][i];
if(x==y)
return y;
for(int i=20;i>=0;i--)
if(fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
return fa[x][0];
}
void pushup(int rt)
{
maxx[rt]=max(maxx[lc[rt]],maxx[rc[rt]]);
}
void insert(int l,int r,int &rt,int pos,int val)//线段树
{
if(!rt)
rt=++tot;
if(l==r)
{
maxx[rt]=make_pair(maxx[rt].first+val,-pos);
return ;
}
int mid=(l+r)>>1;
if(pos<=mid)
insert(l,mid,lc[rt],pos,val);
else
insert(mid+1,r,rc[rt],pos,val);
pushup(rt);
}
int merge(int l,int r,int x,int y)
{
if(!x)
return y;
if(!y)
return x;
if(l==r)
{
maxx[x].first+=maxx[y].first;
return x;
}
int mid=(l+r)>>1;
lc[x]=merge(l,mid,lc[x],lc[y]);
rc[x]=merge(mid+1,r,rc[x],rc[y]);
pushup(x);
return x;
}
void solve(int u)
{
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa[u][0])
{
solve(v);
rt[u]=merge(1,200000,rt[u],rt[v]);
}
}
ans[u]=-maxx[rt[u]].second;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
dep[1]=1;
dfs(1);
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
insert(1,200000,rt[a],c,1);
insert(1,200000,rt[b],c,1);
insert(1,200000,rt[lca(a,b)],c,-1);
insert(1,200000,rt[fa[lca(a,b)][0]],c,-1);
}
solve(1);
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
return 0;
}