【题解】P4556 【模板】线段树合并 / [Vani有约会] 雨天的尾巴
【P4556】题解
一:【题面】
略
二:【解法】
树上差分,暴力累加后缀
可以用线段树合并优化累加速度
三:【代码】
#include<bits/stdc++.h>
#define inf 1e9
using namespace std;
const int N=1e5+10;
vector<int> mp[N];
int fa[N];
namespace __LCA{
int siz[N],son[N],dep[N];
void Son(int u,int pa){
fa[u]=pa;
siz[u]=1;
dep[u]=dep[pa]+1;
for(auto v:mp[u]){
if(v==pa) continue;
Son(v,u);
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
int top[N];
void Line(int u,int tp){
top[u]=tp;
if(!son[u]) return ;
Line(son[u],tp);
for(auto v:mp[u]){
if(v==fa[u]||v==son[u]) continue;
Line(v,v);
}
}
int LCA(int a,int b){
while(top[a]!=top[b]){
if(dep[top[a]]<dep[top[b]]) swap(a,b);
a=fa[top[a]];
}
if(dep[a]>dep[b]) swap(a,b);
return a;
}
}
namespace SEG{
int rt[N];
int idx=0;
struct node{
int son[2];
int maxn;
int pos;
#define ls(q) tree[q].son[0]
#define rs(q) tree[q].son[1]
#define maxn(q) tree[q].maxn
#define pos(q) tree[q].pos
}tree[4*N*(int)log2(N)];
void push_up(int q){
maxn(q)=-inf;
if(maxn(ls(q))>maxn(q)){
maxn(q)=maxn(ls(q));
pos(q)=pos(ls(q));
}
if(maxn(rs(q))>maxn(q)){
maxn(q)=maxn(rs(q));
pos(q)=pos(rs(q));
}
}
void insert(int &q,int l,int r,int tp,int d){
if(q==0) q=++idx;
if(l==r){
maxn(q)+=d;
pos(q)=l;
return ;
}
int mid=l+r>>1;
if(tp<=mid) insert(ls(q),l,mid,tp,d);
else insert(rs(q),mid+1,r,tp,d);
push_up(q);
}
void merge(int &x,int y,int l,int r){
if(!x||!y) return x+=y,void();
if(l==r) return maxn(x)+=maxn(y),void();
int mid=l+r>>1;
merge(ls(x),ls(y),l,mid);
merge(rs(x),rs(y),mid+1,r);
push_up(x);
}
}
int as[N];
void solve(int u){
for(auto v:mp[u]){
if(v==fa[u]) continue;
solve(v);
SEG::merge(SEG::rt[u],SEG::rt[v],1,N-1);
}
if(SEG::maxn(SEG::rt[u])) as[u]=SEG::pos(SEG::rt[u]);
}
int main(){
int n,m;cin>>n>>m;
for(int i=1;i<n;i++){
int a,b;cin>>a>>b;
mp[a].push_back(b);
mp[b].push_back(a);
}
__LCA::Son(1,0);
__LCA::Line(1,1);
while(m--){
int a,b,z;cin>>a>>b>>z;
int lca=__LCA::LCA(a,b);
SEG::insert(SEG::rt[a],1,N-1,z,1);
SEG::insert(SEG::rt[b],1,N-1,z,1);
SEG::insert(SEG::rt[lca],1,N-1,z,-1);
SEG::insert(SEG::rt[fa[lca]],1,N-1,z,-1);
}
solve(1);
for(int i=1;i<=n;i++) cout<<as[i]<<"\n";
return 0;
}

浙公网安备 33010602011771号