zoukankan      html  css  js  c++  java
  • BZOJ 3307: 雨天的尾巴 线段树合并

    写的好丑~

    题解:

    写权值线段树合并时一定要注意一件事情:是否是在线查询或者离线查询.
    离线查询意味着在树上将该点所在线段树建出来后就要马上查询,因为在之后的合并中可能会该边结构.
    这么做的好处就是比较省空间.
    如果要在线查询,那么就一定在合并的时候不能直接将节点信息进行累加,而是每一次都要新建节点.

    // luogu-judger-enable-o2
    // luogu-judger-enable-o2
    #include <cstdio> 
    #include <algorithm>
    #define N 100005 
    #define ls t[x].lson 
    #define rs t[x].rson 
    #define setIO(s) freopen(s".in","r",stdin) , freopen(s".out","w",stdout) 
    using namespace std; 
    int n,m,edges,cnt; 
    int hd[N],nex[N<<1],to[N<<1],fa[N],top[N],dep[N],siz[N],son[N]; 
    int rt[N],tmp;  
    struct Node {
        int lson,rson,max;   
    }t[N*100];           
    inline void addedge(int u,int v) {
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v; 
    }
    void dfs1(int u,int ff) {
        fa[u]=ff,dep[u]=dep[ff]+1,siz[u]=1;    
        for(int i=hd[u];i;i=nex[i]) {
            int v=to[i]; 
            if(v!=ff) {
                dfs1(v,u),siz[u]+=siz[v]; 
                if(siz[v]>siz[son[u]]) son[u]=v; 
            }
        }
    }
    void dfs2(int u,int tp) { 
        top[u]=tp; 
        if(son[u]) dfs2(son[u],tp); 
        for(int i=hd[u];i;i=nex[i]) {
            int v=to[i]; 
            if(v==fa[u]||v==son[u]) continue; 
            dfs2(v,v); 
        }
    }
    int LCA(int x,int y) {
        while(top[x]!=top[y]) {
            dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]]; 
        } 
        return dep[x]<dep[y]?x:y;   
    } 
    void pushup(int x) {
        t[x].max=max(t[ls].max,t[rs].max);      
    }
    int merge(int l,int r,int x,int y) {
        if(!x||!y) return x+y; 
        int xx=++cnt;     
        if(l==r) {     
            t[xx].max=t[y].max+t[x].max;  
            return xx; 
        } 
        int mid=(l+r)>>1;            
        if(mid>=l) t[xx].lson=merge(l,mid,t[x].lson,t[y].lson); 
        if(r>mid) t[xx].rson=merge(mid+1,r,t[x].rson,t[y].rson); 
        pushup(xx);   
        return xx; 
    }
    void update(int l,int r,int &x,int p,int z) {
        if(!x)x=++cnt;      
        if(l==r) {
            t[x].max+=z; 
            return;   
        }   
        int mid=(l+r)>>1;   
        if(p<=mid) update(l,mid,ls,p,z); 
        else update(mid+1,r,rs,p,z); 
        pushup(x);       
    }  
    void dfs(int u,int ff) {
        for(int i=hd[u];i;i=nex[i]) {
            int v=to[i];  
            if(v!=ff) dfs(v,u),rt[u]=merge(1,100000,rt[v],rt[u]);   
        }   
    }
    int find(int l,int r,int x) {
        if(l==r) return l; 
        int mid=(l+r)>>1; 
        if(t[ls].max==tmp) return find(l,mid,ls); 
        else return find(mid+1,r,rs);     
    }
    int main() {
        int i,j; 
        // setIO("input"); 
        scanf("%d%d",&n,&m);                
        for(i=1;i<n;++i) {
            int a,b; 
            scanf("%d%d",&a,&b),addedge(a,b),addedge(b,a);    
        } 
        dfs1(1,0),dfs2(1,1);     
        for(i=1;i<=m;++i) {
            int x,y,z,lca;  
            scanf("%d%d%d",&x,&y,&z);    
            lca=LCA(x,y);  
            update(1,100000,rt[x],z,1), update(1,100000,rt[y],z,1),update(1,100000,rt[lca],z,-1); 
            if(fa[lca]) update(1,100000,rt[fa[lca]],z,-1);   
        }      
        dfs(1,0); 
        for(i=1;i<=n;++i) { 
            tmp=t[rt[i]].max; 
            if(!tmp) printf("%d
    ",tmp); 
            else {
                printf("%d
    ",find(1,100000,rt[i]));    
            }
        }
        return 0; 
    }
    

      

  • 相关阅读:
    XCode
    容器中的诊断与分析4——live diagnosis——LTTng
    容器中的诊断与分析3——live diagnosis——lldb
    容器中的诊断与分析2——live diagnosis——perf
    容器中的诊断与分析1——简介
    HTTP之gRPC
    Markdown介绍
    目标指定法——S.M.A.R.T.
    Facebook token更新
    代理配置
  • 原文地址:https://www.cnblogs.com/guangheli/p/11434584.html
Copyright © 2011-2022 走看看