P4556
题目描述
题解
线段树合并+差分
对于每次修改操作
,我们给
节点打上
的标记,给
,
打上-1的标记
最后计算答案的时候,
一遍,将子树内的值线段树合并,再查询一遍便得到该节点的答案。
代码
#include<bits/stdc++.h>
#define M 1000009
using namespace std;
int read(){
int f=1,re=0;char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-'){f=-1,ch=getchar();}
for(;isdigit(ch);ch=getchar()) re=(re<<3)+(re<<1)+ch-'0';
return re*f;
}
int n,m,rt[M],first[M],nxt[M<<1],to[M<<1],cnt,num,tot,ans[M],rec[M],maxn=M-6,dep[M],f[M][22];
struct tree{int l,r,num,maxn;}tr[M*10];
struct data{int val,num;};
vector<data>a[M];
void del(int x){rec[++num]=x,tr[x].l=tr[x].r=tr[x].maxn=tr[x].num=0;}
int build(){return num?rec[num--]:++cnt;};
void add(int x,int y){nxt[++tot]=first[x],first[x]=tot,to[tot]=y;}
void pushup(int k){
if(tr[tr[k].l].num>=tr[tr[k].r].num&&tr[tr[k].l].num) tr[k].maxn=tr[tr[k].l].maxn,tr[k].num=tr[tr[k].l].num;
if(tr[tr[k].l].num<tr[tr[k].r].num) tr[k].maxn=tr[tr[k].r].maxn,tr[k].num=tr[tr[k].r].num;
}
void update(int &k,int l,int r,int val,int num){
if(!k) k=build();
if(l==r){tr[k].num+=num,tr[k].maxn=l;return;}
int mid=(l+r)>>1;
if(val<=mid) update(tr[k].l,l,mid,val,num);
else update(tr[k].r,mid+1,r,val,num);
pushup(k);
}
int merge(int x,int y,int l,int r){
if(!x||!y) return x+y;
if(l==r){tr[x].num+=tr[y].num;return x;};
int mid=(l+r)>>1;
tr[x].l=merge(tr[x].l,tr[y].l,l,mid);
tr[x].r=merge(tr[x].r,tr[y].r,mid+1,r);
del(y),pushup(x);return x;
}
void dfs1(int u,int fa){
dep[u]=dep[fa]+1;
for(int i=1;i<=20;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int i=first[u];i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
f[v][0]=u,dfs1(v,u);
}
}
int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=20;i>=0;i--){
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
}
for(int i=20;i>=0;i--)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
void dfs2(int u,int fa){
for(int i=0;i<a[u].size();i++) update(rt[u],1,maxn,a[u][i].val,a[u][i].num);
for(int i=first[u];i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
dfs2(v,u),rt[u]=merge(rt[u],rt[v],1,maxn);
}ans[u]=tr[rt[u]].maxn;
}
int main(){
n=read(),m=read();
for(int i=1;i<n;i++){
int x=read(),y=read();
add(x,y),add(y,x);
}dfs1(1,0);
for(int i=1;i<=m;i++){
int u=read(),v=read(),x=read(),lca=getlca(u,v);
a[u].push_back(data{x,1});
a[v].push_back(data{x,1});
a[lca].push_back(data{x,-1});
a[f[lca][0]].push_back(data{x,-1});
}dfs2(1,0);
for(int i=1;i<=n;i++) printf("%d\n",ans[i]);
return 0;
}