P4556-线段树合并,差分

P4556

题目描述

题目描述

题解

线段树合并+差分
对于每次修改操作 ( u , v ) (u,v) ,我们给 u , v u,v 节点打上 + 1 +1 的标记,给 l c a ( u , v ) lca(u,v) , f [ l c a ( u , v ) ] f[lca(u,v)] 打上-1的标记
最后计算答案的时候, d f s dfs 一遍,将子树内的值线段树合并,再查询一遍便得到该节点的答案。

代码

#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;
}
发布了24 篇原创文章 · 获赞 2 · 访问量 657

猜你喜欢

转载自blog.csdn.net/Daniel__d/article/details/105135525
今日推荐