• HDU 5877 [dfs序][线段树][序]


    /*
    题意:
    n个点的树,每个点给定一个权值,给定一个k,求任意一点的子树中,权值小于k/该点权值的点共有多少个。
    思路:
    1.很明显的子树的操作,应用dfs序。
    2.比赛的时候傻逼了,一直在调划分树。实际上这题考虑序关系,加树状数组或者线段树就可以搞定了。
    3.序关系:将权值按照从大到小的顺序排序进行查询,然后按照从小到大的顺序排序进行插入。
    */
    
    
    
    #include<bits/stdc++.h>
    #define N 100050
    using namespace std;
    int ednum;
    struct edge{
        int id;
        edge *next;
    };
    edge edges[N];
    edge *adj[N];
    struct tr{
        int s,e,num;
    };
    tr tree[N*4];
    void build(int s,int e,int k){
        tr &tmp=tree[k];
        tmp.s=s;tmp.e=e;tmp.num=0;
        if(s==e)return;
        int mid=(s+e)>>1;
        build(s,mid,k<<1);
        build(mid+1,e,k<<1|1);
    }
    int cha(int s,int e,int k){
        tr &tmp=tree[k];
        if(tmp.s==s&&tmp.e==e)return tmp.num;
        int mid=(tmp.s+tmp.e)>>1;
        if(e<=mid)return cha(s,e,k<<1);
        else if(s>mid)return cha(s,e,k<<1|1);
        else return cha(s,mid,k<<1)+cha(mid+1,e,k<<1|1);
    }
    void ins(int pos,int k){
        tr &tmp=tree[k];
        if(tmp.s==tmp.e){
            tmp.num++;
            return;
        }
        int mid=(tmp.s+tmp.e)>>1;
        if(pos<=mid)ins(pos,k<<1);
        else ins(pos,k<<1|1);
        tmp.num=tree[k<<1].num+tree[k<<1|1].num;
    }
    inline void addedge(int a,int b){
        edge *tmp=&edges[ednum++];
        tmp->id=b;
        tmp->next=adj[a];
        adj[a]=tmp;
    }
    struct st{
        int id;
        long long val;
    };
    bool cmp1(st a,st b){
        return a.val<b.val;
    }
    bool cmp2(st a,st b){
        return a.val>b.val;
    }
    st sol1[N],sol2[N];
    long long jilu[N];
    int from[N];
    int id[N],siz[N];
    int dfn;
    void dfs(int pos){
        id[pos]=dfn++;
        siz[pos]=1;
        for(edge *it=adj[pos];it;it=it->next){
            dfs(it->id);
            siz[pos]+=siz[it->id];
        }
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--){
            memset(adj,NULL,sizeof(adj));
            memset(from,0,sizeof(from));
            ednum=0;
            int n;
            long long k;
            scanf("%d%lld",&n,&k);
            build(1,n,1);
            for(int i=1;i<=n;i++){
                scanf("%lld",jilu+i);
                sol1[i].id=i;
                sol1[i].val=jilu[i];
                sol2[i]=sol1[i];
            }
            sort(sol1+1,sol1+1+n,cmp1);
            sort(sol2+1,sol2+1+n,cmp2);
            for(int i=1;i<n;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                addedge(a,b);
                from[b]=a;
            }
            int st=1;
            while(from[st]){
                st=from[st];
            }
            dfn=1;
            dfs(st);
            int bf=1;
            long long ans=0;
            for(int i=1;i<=n;i++){
                while(bf<=n&&sol1[bf].val<=k/sol2[i].val){
                    ins(id[sol1[bf].id],1);
                    bf++;
                }
                ans+=cha(id[sol2[i].id],id[sol2[i].id]+siz[sol2[i].id]-1,1);
                ans-=cha(id[sol2[i].id],id[sol2[i].id],1);
            }
            printf("%lld
    ",ans);
        }
    }
  • 相关阅读:
    lyt经典版MySQL基础——进阶6:连接查询-sql92语法-内连接
    lyt经典版MySQL基础——进阶4:常见函数-分组函数
    lyt经典版MySQL基础——进阶2:条件查询
    lyt经典版MySQL基础——进阶1:基础查询
    【转】jmeter如何设置登录接口只调用一次以及遇到的问题:cookie参数放在消息头headers里面
    Kafka命令行操作
    git上无法push代码解决办法
    【转】Jenkins集成Docker镜像实现自动发布
    springboot从一个Controller中的方法跳转到另一个Controller中的方法
    window.open
  • 原文地址:https://www.cnblogs.com/tun117/p/5900534.html
Copyright © 2020-2023  润新知