P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 题解

Link

P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并

Solve

对于每个节点都减一颗权值线段树,然后再用差分的做法,最后统计答案的时候把线段树都合并起来,事实更新最优解

这道题主要是模板,细节蛮多的,要注意

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=100005,maxe=200005;
int N,M;
int cnt,lnk[maxn],nxt[maxe],son[maxe];
int tot,size[maxn],top[maxn],dep[maxn],max_son[maxn],F[maxn],root[maxn],Ans[maxn];
int X[maxn],Y[maxn],Z[maxn],MAXR;

struct node{
	int lson,rson,x;
	LL tot;
}c[6000005];
inline void add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}

void DFS1(int x,int fa){
	size[x]=1;int max_x=-(1<<30);
	for(int j=lnk[x];j;j=nxt[j]){
		if(son[j]==fa)continue;
		dep[son[j]]=dep[x]+1;F[son[j]]=x;
		DFS1(son[j],x);
		size[x]+=size[son[j]];
		if(size[son[j]]>max_x)max_x=size[son[j]],max_son[x]=son[j];
	}
	return ;
}

void DFS2(int x,int fa,int topf){
	top[x]=topf;
	for(int j=lnk[x];j;j=nxt[j]){
		if(son[j]==fa)continue;
		if(son[j]==max_son[x])DFS2(son[j],x,topf);
		else DFS2(son[j],x,son[j]);
	}
}

int LCA(int x,int y){
	while(top[x]^top[y]){
		if(dep[top[x]]<dep[top[y]])swap(x,y);
		x=F[top[x]];
	}
	return dep[x]<dep[y]?x:y;
}

inline int build(){
	++tot;c[tot].lson=c[tot].rson=c[tot].tot=c[tot].x=0;
	return tot;
}

inline void push_up(int x){
	if(c[c[x].lson].tot>=c[c[x].rson].tot)c[x].tot=c[c[x].lson].tot,c[x].x=c[c[x].lson].x;
	else c[x].tot=c[c[x].rson].tot,c[x].x=c[c[x].rson].x;
	return ;
}

int change(int x,int l,int r,int pos,int val){
	if(!x)x=build();
	if(l==r){c[x].tot+=val;c[x].x=l;return x;}
	int mid=(r-l>>1)+l;
	if(pos<=mid) c[x].lson=change(c[x].lson,l,mid,pos,val);
	else c[x].rson=change(c[x].rson,mid+1,r,pos,val);
	push_up(x);
	return x;
}

int merge(int p,int q,int l,int r){
	if(!p)return q;if(!q)return p;
	if(l==r){c[p].tot+=c[q].tot;c[p].x=l;return p;}
	int mid=(r-l>>1)+l;
	c[p].lson=merge(c[p].lson,c[q].lson,l,mid);
	c[p].rson=merge(c[p].rson,c[q].rson,mid+1,r);
	push_up(p);
	return p;
}

void DFS3(int x,int fa){
	for(int j=lnk[x];j;j=nxt[j]){
		if(son[j]==fa)continue;
		DFS3(son[j],x);root[x]=merge(root[x],root[son[j]],1,MAXR);
	}
	if(c[root[x]].tot)Ans[x]=c[root[x]].x;
	return ;
}

inline int read(){
	int ret=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
	return ret*f;
}

int main(){
	freopen("P4556.in","r",stdin);
	freopen("P4556.out","w",stdout);
	N=read();M=read();
	for(int i=1;i<N;i++){
		int x=read(),y=read();
		add_e(x,y);add_e(y,x);
	}
	dep[1]=1;DFS1(1,0);
	DFS2(1,0,1);
	for(int i=1;i<=M;i++){
		X[i]=read(),Y[i]=read(),Z[i]=read();MAXR=max(MAXR,Z[i]);
	}
	for(int i=1;i<=M;i++){
		int lca=LCA(X[i],Y[i]);
		root[X[i]]=change(root[X[i]],1,MAXR,Z[i],1);
		root[Y[i]]=change(root[Y[i]],1,MAXR,Z[i],1);
		root[lca]=change(root[lca],1,MAXR,Z[i],-1);
		if(F[lca])root[F[lca]]=change(root[F[lca]],1,MAXR,Z[i],-1);
	}
	DFS3(1,0);
	for(int i=1;i<=N;i++)printf("%d
",Ans[i]);
	return 0;
}
原文地址:https://www.cnblogs.com/martian148/p/14083836.html