模板
#include<iostream>
#include<vector>
using namespace std;
const int Z=100000;
int n,m;
vector<vector<int>> a;
int deep[100005],f[20][100005],*fa=f[0],size[100005];
int dfs1(int u) {
size[u]=1;
deep[u]=deep[fa[u]]+1;
for(auto&v:a[u]) {
if(v==fa[u]) continue;
fa[v]=u;
size[u]+=dfs1(v);
}
return size[u];
}
int LCA(int x,int y) {
if(deep[x]<deep[y]) swap(x,y);
for(int k=19; k>=0; k--)
if(deep[f[k][x]]>=deep[y])
x=f[k][x];
if(x==y) return x;
for(int k=19; k>=0; k--)
if(f[k][x]^f[k][y])
x=f[k][x],
y=f[k][y];
return fa[x];
}
struct node {
int l,r;
pair<int,int> v;//最大值权值,最大值的最小编号的相反数
int lc,rc;
} t[100010*100]; //注意空间
int cnt;
int newn(int u,bool flag) {//newnode
int mid=t[u].l+t[u].r>>1;
if(!flag)//左儿子
t[t[u].lc=++cnt]= {t[u].l,mid,{-1e9,-t[u].l},0,0}; //最大值编号先为左端点
else
t[t[u].rc=++cnt]= {mid+1,t[u].r,{-1e9,-mid-1},0,0};
return cnt;
}
void push_up(int u) {
t[u].v={-1e9,-1e9};
if(t[u].lc) t[u].v=max(t[u].v,t[t[u].lc].v);
if(t[u].rc) t[u].v=max(t[u].v,t[t[u].rc].v);
}
void push(int u,int p,int v) {
if(t[u].l==t[u].r&&t[u].l==p)
if(t[u].v.first==-1e9)
t[u].v.first=v;
else
t[u].v.first+=v;
else {
int mid=t[u].l+t[u].r>>1;
if(p<=mid)
if(t[u].lc) push(t[u].lc,p,v);
else push(newn(u,0),p,v);
else if(t[u].rc) push(t[u].rc,p,v);
else push(newn(u,1),p,v);
push_up(u);
}
if(!t[u].v.first)
t[u].v.first=-1e9;
}
pair<int,int> find(int u,int l,int r) {
if(l<=t[u].l&&t[u].r<=r)
return t[u].v;
int mid=t[u].l+t[u].r>>1;
pair<int,int> ans= {-1e9,-1e9};
if(l<=mid&&t[u].lc)
ans=max(ans,find(t[u].lc,l,r));
if(mid<r&&t[u].rc)
ans=max(ans,find(t[u].rc,l,r));
return ans;
}
void merge(int u1,int u2) {
//u1<-u2
if(t[u1].lc&&t[u1].rc) {
if(t[u2].lc) merge(t[u1].lc,t[u2].lc);
if(t[u2].rc) merge(t[u1].rc,t[u2].rc);
} else {
if(t[u1].lc&&t[u2].lc) merge(t[u1].lc,t[u2].lc);
if(!t[u1].lc) t[u1].lc=t[u2].lc;
if(t[u1].rc&&t[u2].rc) merge(t[u1].rc,t[u2].rc);
if(!t[u1].rc) t[u1].rc=t[u2].rc;
if(!t[u1].lc&&!t[u1].rc) {
if(t[u2].v.first^(int)-1e9) {
if(t[u1].v.first==-1e9)
t[u1].v.first=t[u2].v.first;
else
t[u1].v.first+=t[u2].v.first;
if(!t[u1].v.first)
t[u1].v.first=-1e9;
}
}
}
if(t[u1].lc||t[u1].rc)push_up(u1);
}
int ans[100005];
void dfs2(int u) {
for(auto&v:a[u])
if(v^fa[u])
dfs2(v),merge(u,v);
pair<int,int> ansx=find(u,1,Z);
ans[u]=ansx.first==-1e9?0:-ansx.second;
}
int main() {
cin>>n>>m;
a.resize(n+1);
for(int i=1; i<n; i++) {
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
dfs1(1);
// for(int i=1;i<=n;i++)
// cout<<fa[i]<<' ';
// cout<<endl;
for(int k=1; k<20; k++)
for(int i=1; i<=n; i++)
f[k][i]=f[k-1][f[k-1][i]];
for(int i=1; i<=n; i++) //前n个节点必然是根节点
t[i]= {1,Z,{-1e9,0},0,0};
cnt=n;
while(m--) {
int x,y,z;
cin>>x>>y>>z;
int lca=LCA(x,y);
push(x,z,1);
push(y,z,1);
push(lca,z,-1);
if(fa[lca]) push(fa[lca],z,-1);
}
dfs2(1);
for(int i=1; i<=n; i++)
cout<<ans[i]<<endl;
return 0;
}
- 注意当线段树节点权值为0的时候置为负无穷
- 注意merge中,必须有孩子才能push_up
后记
于是皆大欢喜。