zoukankan      html  css  js  c++  java
  • 主席树+树链剖分——南昌邀请赛Distance on the tree

    学了差不多一星期的主席树+树链剖分,再来看这题发现其实是个板子题

    一开始想复杂了,以为要用类似求树上第k大的树上差分思想来解决这道题,但其实树链上<=k的元素个数其实直接可以用树链剖分来求

    具体是把每条树链放到主席树上询问一下求和就好了

    #include<bits/stdc++.h>
    using namespace std;
    #define maxn 100006
    struct Edge{int to,nxt,w;}edge[maxn<<1];
    int b[maxn],n,m,a[maxn],head[maxn],tot; 
    void init(){memset(head,-1,sizeof head);tot=0;}
    void addedge(int u,int v,int w){
        edge[tot].to=v;edge[tot].nxt=head[u];edge[tot].w=w;head[u]=tot++;
    }
    struct Node{int lc,rc,sum;}T[maxn*25];
    int siz,rt[maxn];
    int build(int l,int r){
        int now=++siz;
        T[now].lc=T[now].rc=T[now].sum=0;
        if(l==r)return now;
        int mid=l+r>>1;
        T[now].lc=build(l,mid);
        T[now].rc=build(mid+1,r); 
        return now;
    }    
    int update(int last,int pos,int l,int r){//更新到pos点 
        int now=++siz;
        T[now]=T[last];T[now].sum++;
        if(l==r)return now;
        int mid=l+r>>1;
        if(pos<=mid)T[now].lc=update(T[last].lc,pos,l,mid);
        else T[now].rc=update(T[last].rc,pos,mid+1,r);
        return now;
    }    
    int query(int st,int ed,int L,int R,int l,int r){
        if(L<=l && R>=r)return T[ed].sum-T[st].sum;
        int mid=l+r>>1,res=0;
        if(L<=mid)res+=query(T[st].lc,T[ed].lc,L,R,l,mid);
        if(R>mid)res+=query(T[st].rc,T[ed].rc,L,R,mid+1,r);
        return res;
    }    
    
    int f[maxn],son[maxn],d[maxn],size[maxn];
    void dfs1(int x,int pre,int deep){
        f[x]=pre;size[x]=1;d[x]=deep;
        for(int i=head[x];i!=-1;i=edge[i].nxt){
            int y=edge[i].to;
            if(y==pre)continue;
            a[y]=edge[i].w;
            dfs1(y,x,deep+1);
            size[x]+=size[y];
            if(size[y]>size[son[x]])son[x]=y;
        }
    }
    int id[maxn],rk[maxn],idx,top[maxn];
    void dfs2(int x,int tp){
        top[x]=tp;id[x]=++idx;rk[idx]=x;
        if(son[x])dfs2(son[x],tp);
        for(int i=head[x];i!=-1;i=edge[i].nxt){
            int y=edge[i].to;
            if(y!=son[x] && y!=f[x])dfs2(y,y);
        }
    }
    
    int Query(int x,int y,int pos){
           int res=0;
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            res+=query(rt[id[top[x]]-1],rt[id[x]],1,pos,1,m);
            x=f[top[x]];
        }
        if(id[x]>id[y])swap(x,y);
        res+=query(rt[id[x]],rt[id[y]],1,pos,1,m);
        return res;
    }
    int main(){int q;init();
        cin>>n>>q;int u,v,w,k;
        for(int i=1;i<n;i++){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);addedge(v,u,w);
        }
        
        a[1]=0x3f3f3f3f;
        siz=0;dfs1(1,1,1);dfs2(1,1);//树剖 
        for(int i=1;i<=n;i++)b[++m]=a[i];
        sort(b+1,b+1+m);
        m=unique(b+1,b+1+m)-(b+1);
        rt[0]=build(1,m);
        for(int i=1;i<=idx;i++){
            int pos=lower_bound(b+1,b+1+m,a[rk[i]])-b;
            rt[i]=update(rt[i-1],pos,1,m);
        }
        
        while(q--){
            scanf("%d%d%d",&u,&v,&k);
            int pos=upper_bound(b+1,b+1+m,k)-(b+1);
            if(pos==0){puts("0");continue;}
            else cout<<Query(u,v,pos)<<'
    ';
        } 
    }
  • 相关阅读:
    由类型名得到该类型
    TypeName of CA1505 is AvoidUnmaintainableCode, not AvoidUnmantainableCode.
    多核
    SSRS throws "The operation has timed out."
    XmlRootAttribute与XmlTypeAttribute
    littleendian and bigendian
    Assembly Exp
    如何在Ubuntu 11.10下成功安装Java [转载]
    *uck up ~,纯发泄
    [转载]读书相关,,
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10772061.html
Copyright © 2011-2022 走看看