ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-08-08 17:34:19  阅读:164  来源: 互联网

标签:rt lc P4556 ll tree sm rc Vani 模板


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

线段树合并+树上差分。

模板题啊。

线段树合并和 Treap 合并还挺像的,就是从根节点开始将小的合并到大的上面去,然后合并的时候在大的上面做一下处理就好了。。。

这里写的是离线写法。。但这种写法是会破坏大线段树的结构的。。。

inline ll merge(ll l,ll r,ll x,ll y){
    if(!x||!y)  return x+y;
    if(l==r){
        tree[x].sm+=tree[y].sm;
        return x;
    }
    ll mid=(l+r)>>1;
    lc[x]=merge(l,mid,lc[x],lc[y]);
    rc[x]=merge(mid+1,r,rc[x],rc[y]);
    pushup(x);
    return x;
}//核心代码

inline void solve(ll x,ll fat){
    for(register int i=hd[x];i;i=e[i].nx){
        ll to=e[i].to;
        if(to==fat)   continue;
        solve(to,x);
        rt[x]=merge(1,maxn,rt[x],rt[to]);
    }
    ans[x]=(!tree[rt[x]].sm?0:tree[rt[x]].id);
}

还有一种在线写法只是很耗空间。。。每一次新开一个节点。。。

把离线的 \(x\) 改为 \(root\) ,然后每一次合并操作在 \(tree[root]\) 上操作就行了。。。

代码不放了。

至于每个节点建一颗线段树。。。和主席树很像。。。每一次保存一个点 \(x\) 所拥有的线段树最上面的那个点记作 \(rt[x]\) ,虽然最后都是在 \(tree\) 数组上进行操作的但是很明显 \(rt\) 与 \(rt\) 之间并没有直接关系(也没有边连接

不能之间传 \(l\) ,\(r\) 的参了,要开 \(lc\) 和 \(rc\) 数组。。。

呃,没了。

#include <bits/stdc++.h>
#define ll long long
#define maxn 2000001
using namespace std;
ll n,m,u,v,w;
ll hd[maxn],cnt;
ll rt[maxn<<2],tot;
ll lc[maxn<<2],rc[maxn<<2];
ll ans[maxn<<2];
ll fa[maxn],top[maxn];
ll dep[maxn],val[maxn],son[maxn];
struct Node{
    ll nx,to;
}e[maxn<<1];
struct NoDe{
    ll sm=0,id=0;
}tree[maxn<<2];

inline ll read(){
    ll x=0,f=0;char c=getchar();
    while(!isdigit(c))  f|=c=='-',c=getchar();
    while(isdigit(c))   x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return f?-x:x;
}

inline void add(ll u,ll v){
    e[++cnt].to=v;
    e[cnt].nx=hd[u];
    hd[u]=cnt;
}

inline void dfs1(ll x){
    dep[x]=dep[fa[x]]+1;
    val[x]=1;
    for(register int i=hd[x];i;i=e[i].nx){
        ll to=e[i].to;
        if(to==fa[x])   continue;
        fa[to]=x;
        dfs1(to);
        val[x]+=val[to];
        if(val[son[x]]<val[to]||!son[x])
            son[x]=to;
    }
}

inline void dfs2(ll x,ll tp){
    top[x]=tp;
    if(son[x])  dfs2(son[x],tp);
    for(register int i=hd[x];i;i=e[i].nx)   
        if(e[i].to!=fa[x]&&e[i].to!=son[x])
            dfs2(e[i].to,e[i].to);
}

inline ll LCA(ll x,ll y){
    for(;top[x]!=top[y];dep[top[x]]<dep[top[y]]?y=fa[top[y]]:x=fa[top[x]]);
    return dep[x]<dep[y]?x:y;
}

inline void pushup(ll f){
    if(!lc[f]){
        tree[f].sm=tree[rc[f]].sm;
        tree[f].id=tree[rc[f]].id;
        return;
    }
    if(!rc[f]){
        tree[f].sm=tree[lc[f]].sm;
        tree[f].id=tree[lc[f]].id;
        return;
    }
    if(tree[lc[f]].sm>=tree[rc[f]].sm){
        tree[f].sm=tree[lc[f]].sm;
        tree[f].id=tree[lc[f]].id;
    }
    else{
        tree[f].sm=tree[rc[f]].sm;
        tree[f].id=tree[rc[f]].id;
    }
}

inline void update(ll l,ll r,ll &f,ll x,ll y){
    if(!f)  f=++tot;
    if(l==r){
        tree[f].sm+=y;
        tree[f].id=x;
        return;
    }
    ll mid=(l+r)>>1;
    if(x<=mid)      update(l,mid,lc[f],x,y);
    else            update(mid+1,r,rc[f],x,y);
    pushup(f);
}

inline ll merge(ll l,ll r,ll x,ll y){
    if(!x||!y)  return x+y;
    if(l==r){
        tree[x].sm+=tree[y].sm;
        return x;
    }
    ll mid=(l+r)>>1;
    lc[x]=merge(l,mid,lc[x],lc[y]);
    rc[x]=merge(mid+1,r,rc[x],rc[y]);
    pushup(x);
    return x;
}

inline void solve(ll x,ll fat){
    for(register int i=hd[x];i;i=e[i].nx){
        ll to=e[i].to;
        if(to==fat)   continue;
        solve(to,x);
        rt[x]=merge(1,maxn,rt[x],rt[to]);
    }
    ans[x]=(!tree[rt[x]].sm?0:tree[rt[x]].id);
}

int main(){
    n=read();m=read();
    for(register int i=1;i<n;++i){
        u=read();v=read();
        add(u,v);
        add(v,u);
    }
    dfs1(1);
    dfs2(1,1);
    for(register int i=1;i<=m;++i){
        u=read();v=read();w=read();
        ll lca=LCA(u,v);
        update(1,maxn,rt[u],w,1);
        update(1,maxn,rt[v],w,1);
        update(1,maxn,rt[lca],w,-1);
        update(1,maxn,rt[fa[lca]],w,-1);
    }
    solve(1,0);
    for(register int i=1;i<=n;++i)
        printf("%lld\n",ans[i]);
    return 0;
}

标签:rt,lc,P4556,ll,tree,sm,rc,Vani,模板
来源: https://www.cnblogs.com/sissi/p/15115436.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有