bzoj3307雨天的尾巴(线段树合并)

来源:互联网 发布:淘宝群怎么能快速拉人 编辑:程序博客网 时间:2024/04/30 13:12

Description

N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
所有发放后,每个点存放最多的是哪种物品。

Input

第一行数字N,M
接下来N-1行,每行两个数字a,b,表示a与b间有一条边
再接下来M行,每行三个数字x,y,z.如题

Output

输出有N行
每i行的数字表示第i个点存放最多的物品是哪一种,如果有
多种物品的数量一样,输出编号最小的。如果某个点没有物品
则输出0

我们首先可以树上差分一下贡献,然后线段树自下而上合并就好了.
(启发式合并应该更靠谱,然而我动态开点后并不会维护size,维护了反而可能MLE,最后暴力合并一发A了,只是卡了发评测...)

#include <cstdio>#include <iostream>#include <cstring>#define maxn 100005#define maxx 200005#define mem(a,b) memset(a,b,sizeof(a))using namespace std;inline void read(int& x){   char c=getchar();x=0;int y=1;    while(c<'0'||c>'9'){if(c=='-') y=-1;c=getchar();}    while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();    x*=y;}const int VMAX=1e9;inline int m_max(int x,int y){return x>y?x:y;}int n,m,son[maxn],ssum[maxn],top[maxn],fa[maxn],dp[maxn],ans[maxn],num,hea[maxn];struct road{int en,nex;}ro[maxx];inline void add(int x,int y){ro[num].en=y;ro[num].nex=hea[x];hea[x]=num++;}inline void dfs(int x,int y=0){   ssum[x]=1;fa[x]=y;dp[x]=dp[y]+1;    for(int i=hea[x];i!=-1;i=ro[i].nex)    {   int v=ro[i].en;        if(v==y) continue;        dfs(v,x);ssum[x]+=ssum[v];        if(!son[x]||ssum[son[x]]<ssum[v]) son[x]=v;    }}inline void redfs(int x,int y=1){   top[x]=y;    if(!son[x]) return;    redfs(son[x],y);    for(int i=hea[x];i!=-1;i=ro[i].nex)    {   int v=ro[i].en;        if(v!=fa[x]&&v!=son[x]) redfs(v,v);    }}inline int flca(int x,int y){   int t1=top[x],t2=top[y];    while(t1!=t2)    {   if(dp[t1]<dp[t2]) std::swap(t1,t2),std::swap(x,y);        x=fa[t1];t1=top[x];    }    if(dp[x]>dp[y]) std::swap(x,y);    return x;}struct tree{   tree *lch,*rch;int ma;    tree():lch(NULL),rch(NULL),ma(0){}    inline int mval(){return this?this->ma:0;}    inline void mt(){this->ma=m_max(this->lch->mval(),this->rch->mval());}}*root[maxn];inline void update(tree*& now,int x,int l,int r,int z){   if(!now) now=new tree();    if(l==r){now->ma+=z;return;}    int mid=l+r>>1;    if(x<=mid) update(now->lch,x,l,mid,z);    else update(now->rch,x,mid+1,r,z);    now->mt();}inline void merge(tree*& x,tree* y,int l,int r){   if(!y) return;if(!x){x=y;return;}    if(l==r){x->ma+=y->ma;return;}    int mid=l+r>>1;    merge(x->lch,y->lch,l,mid);merge(x->rch,y->rch,mid+1,r);    x->mt();}inline int dfs4(tree* x,int y,int l,int r){   if(!x) return 0;    if(l==r) return l;    int mid=l+r>>1;    if(x->lch->mval()==y) return dfs4(x->lch,y,l,mid);    else return dfs4(x->rch,y,mid+1,r);}inline void dfs3(int x,int y=0){   for(int i=hea[x];i!=-1;i=ro[i].nex)    {   int v=ro[i].en;        if(v==y) continue;        dfs3(v,x);        merge(root[x],root[v],1,VMAX);    }    if(root[x]->mval())        ans[x]=dfs4(root[x],root[x]->mval(),1,VMAX);}int main(){   read(n);read(m);int x=0,y=0,z=0;mem(hea,-1);    for(int i=1;i<n;++i)    {   read(x);read(y);        add(x,y);add(y,x);    }    dfs(1);redfs(1);    for(int i=1;i<=m;++i)    {   read(x);read(y);read(z);        int tmp=flca(x,y);        update(root[x],z,1,VMAX,1);        update(root[y],z,1,VMAX,1);        update(root[tmp],z,1,VMAX,-1);        if(fa[tmp]) update(root[fa[tmp]],z,1,VMAX,-1);    }    dfs3(1);    for(int i=1;i<=n;++i) printf("%d\n",ans[i]);    return 0;}
原创粉丝点击