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\n",tmp); 
        else {
            printf("%d\n",find(1,100000,rt[i]));    
        }
    }
    return 0; 
}

  

posted @ 2019-08-30 13:44  EM-LGH  阅读(127)  评论(0编辑  收藏  举报