正题
题目链接:https://www.luogu.org/problemnew/show/P4556
题目大意
nnn个点的一棵树,给出mmm个操作(x,y,z)(x,y,z)(x,y,z)表示将xxx到yyy的路径上的所有点给与一个zzz类型的食量。
最后对于每个点输出最多的粮食类型。
解题思路
先对这棵树进行树剖,然后对于每个x,yx,yx,y我们将其拆成若干条在重链上连续的路径,然后我们就可以对于每一条重链单独进行操作,这样就成为了一个序列问题。
将zzz离散化以后再线段树上进行操作,维护一个(w,loc)(w,loc)(w,loc)表示最多的粮食数,这个粮食的类型。然后每次遇到一个左端点就在zzz处+1+1+1,遇到右端点就在zzz处−1-1−1。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N=110000;
struct Edge_node{int to,next;
}a[N<<1];
struct Path_node{int w,z;
}q[N*30];
struct Tree_node{int l,r,w,loc;
};
int n,m,cnt,tot,ls[N],fa[N],from[N],ans[N];
int b[N],seg[N],id[N],siz[N],son[N],dep[N],top[N];
struct Seg_Tree{Tree_node t[N<<2]; void Merge(int x,int ls,int rs){t[x].w=max(t[ls].w,t[rs].w);if(t[x].w==t[ls].w) t[x].loc=t[ls].loc;else t[x].loc=t[rs].loc;}void Build(int x,int l,int r){t[x].l=l;t[x].r=r;if(l==r){t[x].w=0;t[x].loc=0;return;}int mid=(l+r)/2;Build(x*2,l,mid);Build(x*2+1,mid+1,r);Merge(x,x*2,x*2+1);}void Change(int x,int pos,int w){if(t[x].l==t[x].r){t[x].w+=w;t[x].loc=pos;if(!t[x].w) t[x].loc=0;return;}if(pos<=t[x*2].r) Change(x*2,pos,w);else Change(x*2+1,pos,w);Merge(x,x*2,x*2+1);}int Query(){return t[1].loc;}
}Tree;
void addl(int x,int y)
{a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;
}
void dfs1(int x)
{siz[x]=1;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x]) continue;dep[y]=dep[x]+1;fa[y]=x;dfs1(y);siz[x]+=siz[y];if(siz[y]>siz[son[x]]) son[x]=y;}
}
void dfs2(int x)
{seg[x]=++cnt;id[cnt]=x;from[cnt]=top[x];if(son[x]){top[son[x]]=top[x];dfs2(son[x]);}for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(y==fa[x]||y==son[x]) continue;top[y]=y;dfs2(y);}
}
void Apart_path(int x,int y,int z)
{while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]) swap(x,y);q[++cnt]=(Path_node){seg[top[x]],z};q[++cnt]=(Path_node){seg[x]+1,-z};x=fa[top[x]];}if(dep[x]>dep[y]) swap(x,y);q[++cnt]=(Path_node){seg[x],z};q[++cnt]=(Path_node){seg[y]+1,-z};
}
bool cmp(Path_node x,Path_node y)
{return x.w<y.w;}
int main()
{scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addl(x,y);addl(y,x);}dfs1(1);dfs2(1);cnt=0;for(int i=1;i<=m;i++){int x,y,w;scanf("%d%d%d",&x,&y,&w);Apart_path(x,y,w);b[i]=w;}sort(b+1,b+1+m);m=unique(b+1,b+1+m)-b-1;sort(q+1,q+1+cnt,cmp);int l=1;Tree.Build(1,1,max(m,1));for(int i=1;i<=n;i++){while(q[l].w<=i&&l<=cnt){int w=lower_bound(b+1,b+1+m,abs(q[l].z))-b;Tree.Change(1,w,(q[l].z<0)?-1:1);l++;}ans[id[i]]=b[Tree.Query()];}for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
}