【题解】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;
}
posted @ 2025-12-29 15:18  Ming3398  阅读(18)  评论(0)    收藏  举报