雨天的尾巴

天大地大妈咪最大 提交于 2019-11-29 19:05:22

洛谷

线段树合并模板题

不说了直接代码分析

大佬的code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<ctime>
using namespace std;
#define ll long long
#define N 101000
#define Z 100000
#define inf 1e9
#define RG register
#define re return
inline ll read(){
    RG ll x=0,t=1;RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}

int n,m,top,first[N],ans[N];

struct mona {int nxt,en;}s[N<<1];

struct joker{int nxt,en,op;};

inline void Insert(int x,int y) 
{ 
    s[++top]=(mona){first[x],y};
    first[x]=top; 
}

struct SeqTree{
    int cnt,ls[N*40],rs[N*40],Max[N*40],id[N*40],rt[N],rab[N*40],tot,top,first[N]; joker s[N<<2]; 
    
    inline void Insert(int x,int y,int op) //差分起始 
    { 
        s[++top]=(joker){first[x],y,op};
        first[x]=top; 
    }
    
    inline int New() 
    {
         if(tot)
         re rab[tot--]; 
        re ++cnt;
    }
    inline void Throw(int x) 
    { 
        rab[++top]=x;
        ls[x]=rs[x]=Max[x]=id[x]=0; 
    }
    inline void Pushup(int x)
    {
        if(Max[ls[x]]>=Max[rs[x]]) 
            Max[x]=Max[ls[x]],id[x]=id[ls[x]];
        else Max[x]=Max[rs[x]],id[x]=id[rs[x]];
    }
    
    inline void Modify(int l,int r,int &x,int pos,int val)
    {
        if(!x) x=New(); 
        if(l==r) 
        { 
            Max[x]+=val;
            id[x]=l;
        }
        else
        {
            int mid=l+r>>1;
            if(pos<=mid) Modify(l,mid,ls[x],pos,val);
            else 
                Modify(mid+1,r,rs[x],pos,val);
            Pushup(x);
        } 
        if(!Max[x]) id[x]=0;//回收机制处理 
    }
    inline int Merge(int l,int r,int u,int v)//并一波线段树  
    {
        if(!u||!v) return u|v;
        int now=New(),mid=l+r>>1; 
        
        if(l==r) Max[now]=Max[u]+Max[v],id[now]=l;//MAX,id同步 
        else 
        {
            ls[now]=Merge(l,mid,ls[u],ls[v]);
            rs[now]=Merge(mid+1,r,rs[u],rs[v]);
            Pushup(now);
        } 
        Throw(u);
        Throw(v); 
        //biu,扔进垃圾桶 
        re now;
    }
} T;

struct Tree{
    int top[N],son[N],siz[N],fa[N],dep[N];
    inline void Dfs(int k,int Fa){
        fa[k]=Fa,siz[k]=1,dep[k]=dep[Fa]+1;
        for(RG int i=first[k];i;i=s[i].nxt){
            int en=s[i].en; if(en==Fa) continue ;
            Dfs(en,k),siz[k]+=siz[en];
            if(siz[son[k]]<siz[en]) son[k]=en;
        }   return ;
    }
    inline void Dfs2(int k,int to){
        top[k]=to; if(son[k]) Dfs2(son[k],to);
        for(RG int i=first[k];i;i=s[i].nxt){
            int en=s[i].en; if(en==fa[k]||en==son[k]) continue ;
            Dfs2(en,en);
        }
    }
    inline int Lca(int u,int v){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            u=fa[top[u]];
        }   return dep[u]<dep[v]?u:v;
    }
} S;//LCA树 

inline void Dfs(int k,int fa)
{
    for(RG int i=first[k];i;i=s[i].nxt) 
    if(s[i].en!=fa) Dfs(s[i].en,k);
    
    for(RG int i=T.first[k];i;i=T.s[i].nxt) 
        T.Modify(1,Z,T.rt[k],T.s[i].en,T.s[i].op);//加入 
        
    ans[k]=T.id[T.rt[k]];
    
    if(S.fa[k])//存在父亲 
        T.rt[S.fa[k]]=T.Merge(1,Z,T.rt[S.fa[k]],T.rt[k]);
        //并 
        
    re;
}

int main(){
    freopen("in.txt","r",stdin);
    n=read(),m=read();
    
    for(RG int i=1;i<n;++i)
    {
        int x=read(),y=read();
        Insert(x,y),Insert(y,x);//add边 
    }  
    
    //剖一波 
     S.Dfs(1,0);
     S.Dfs2(1,1);
      
    for(RG int i=1;i<=m;++i)
    {
        int u=read(),v=read(),val=read();
        int lca=S.Lca(u,v),Flca=S.fa[lca];//LCA
        //差分一下 
        T.Insert(u,val,1),T.Insert(v,val,1),T.Insert(lca,val,-1),T.Insert(Flca,val,-1);
    }   
    Dfs(1,0); //总来一起统计 
    for(RG int i=1;i<=n;++i) printf("%d\n",ans[i]);
}

 

蒟蒻的

有一点问题就是

权值线段树

貌似可以不用离散化

/*
while(next second)
++love_life;
*/
#include<bits/stdc++.h>
#define re return
#define R register 
#define inc(i,l,r) for(register int i=l;i<=r;++i)
using namespace std;
template<typename T>inline void rd(T&x)
{
    char c;bool f=0;
    while((c=getchar())<'0'||c>'9')if(c=='-')f=1;
    x=c^48;
    while((c=getchar())>='0'&&c<='9')x=x*10+(c^48);
    if(f)x=-x;
}

const int maxn=1e5+5,maxl=1e5;

int n,m,k,hd[maxn],hide[maxn],X[maxn],Y[maxn],Z[maxn],a[maxn];
int ans[maxn];

struct node{
    int to,nt;
}e[maxn<<1];
inline void add(int x,int y)
{
    e[++k].to=y;e[k].nt=hd[x];hd[x]=k;
    e[++k].to=x;e[k].nt=hd[y];hd[y]=k;
}

struct tree
{
    int first[maxn],top,tot,cnt;
    int rab[maxn*30],rt[maxn*30],id[maxn*30],ls[maxn*30],rs[maxn*30],Max[maxn*30];
    struct LL
    {
        int col,nt,op;
    }st[maxn<<2];
    
    inline void insert(int x,int y,int z)
    //节点X染成y,+-z 
    {
        st[++top].col=y;st[top].nt=first[x];first[x]=top;st[top].op=z;
    }
    
    inline int New()
    {
        int now;
        if(tot)now=rab[tot--];
        else now=++cnt;
        ls[now]=rs[now]=Max[now]=0;
        re now;
    }
    
    inline void Throw(int x)
    {
        rab[++tot]=x;
    }
    
    inline void pushup(int rt)
    {
        if(Max[ls[rt]]<Max[rs[rt]])
            Max[rt]=Max[rs[rt]],id[rt]=id[rs[rt]];
        else 
            Max[rt]=Max[ls[rt]],id[rt]=id[ls[rt]];
    }
    
    inline void Add(int &rt,int l,int r,int pos,int val)
    {
        if(!rt)
            rt=New();
        if(l==r)
        {
            Max[rt]+=val; 
            id[rt]=l;
            re;
        }
        
        int mid=(l+r)>>1;
        if(pos<=mid) Add(ls[rt],l,mid,pos,val);
        else Add(rs[rt],mid+1,r,pos,val);
        pushup(rt);
        if(!Max[rt]) id[rt]=0;
    }
    
    inline int merge(int l,int r,int x,int y)
    {
        if(!x||(!y))re x+y;
        if(l==r)
        {
            Max[x]+=Max[y];
            Throw(y);
            re x;
        }
        
        int mid=(l+r)>>1;
        ls[x]=merge(l,mid,ls[x],ls[y]);
        rs[x]=merge(mid+1,r,rs[x],rs[y]);
        Throw(y);
        pushup(x);
        re x;
    }
    

}T;

struct LCA
{
    int fa[maxn],top[maxn],son[maxn],size[maxn],dep[maxn];
    
    inline void dfs1(int x)
    {
        dep[x]=dep[fa[x]]+(size[x]=1);
        for(int i=hd[x];i;i=e[i].nt)
        {
            int v=e[i].to;
            if(v==fa[x])continue;
            fa[v]=x;
            dfs1(v);
            size[x]+=size[v];
            if(size[v]>size[son[x]])
            son[x]=v;
        }
    }
    
    inline void dfs2(int x,int topf)
    {
        top[x]=topf;
        if(son[x])
        {
            dfs2(son[x],topf);
            for(int i=hd[x];i;i=e[i].nt)
            {
                int v=e[i].to;
                if(!top[v])
                dfs2(v,v);
            }
        }    
    }
    
    inline int Lca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])x^=y^=x^=y;
            x=fa[top[x]];
        }
        re dep[x]<dep[y]?x:y;
    }
}S;

inline void dfs(int x)
{
    for(int i=hd[x];i;i=e[i].nt)
    {
        int v=e[i].to;
        if(v==S.fa[x])continue;
        dfs(v);
    }
    
    for(int i=T.first[x];i;i=T.st[i].nt)
        T.Add(T.rt[x],1,maxl,T.st[i].col,T.st[i].op);
    ans[x]=T.id[T.rt[x]];
    
    if(S.fa[x])T.rt[S.fa[x]]=T.merge(1,maxl,T.rt[S.fa[x]],T.rt[x]);
}

int main()
{
    freopen("in.txt","r",stdin);
    int x,y,z;
    rd(n),rd(m);
    inc(i,2,n)
    {
        rd(x),rd(y);
        add(x,y);
    }
    
    S.dfs1(1);
    S.dfs2(1,1);
        
    inc(i,1,m)
    {
        rd(X[i]),rd(Y[i]),rd(Z[i]);
        a[i]=Z[i];
    }    
    //离散化
    sort(a+1,a+m+1);
    int N=unique(a+1,a+m+1)-a-1;
    
    inc(i,1,N)hide[i]=a[i];
    
    inc(i,1,m)
    {
        int lca=S.Lca(X[i],Y[i]),flca=S.fa[lca];
        
        int pos=lower_bound(a+1,a+N+1,Z[i])-a;

        T.insert(X[i],pos,1);T.insert(Y[i],pos,1);
        T.insert(lca,pos,-1);T.insert(flca,pos,-1);
    }
    
    dfs(1);
    inc(i,1,n)
    printf("%d\n",hide[ans[i]]);
    re 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!