• HDU 5877 Weak Pair(树状数组)


    【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5877

     

    【题目大意】

       给出一棵带权有根树,询问有几对存在祖先关系的点对满足权值相乘小于等于k。

    【题解】

      我们沿根节点开始将点权加入权值树状数组,每次处理完子树就回溯,保证每个节点的答案统计是在只包括祖先节点的树状数组中进行。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int N=100005;
    long long a[N],disc[N],k;
    int c[N],ans,b[N],d[N],T,n;
    vector<int> v[N];
    int add(int x,int num){while(x<N)c[x]+=num,x+=x&-x;}
    int query(int x){int s=0;while(x)s+=c[x],x-=x&-x;return s;}
    int remark(long long x){
          int l=1,r=n;
          while(l<=r){
                int mid=(l+r)>>1;
                if(disc[mid]<x)l=mid+1;
                else if(disc[mid]==x)return mid;
                else r=mid-1;
          }
    }
    void dfs(int x){
        add(b[x],1);
        for(int i=0;i<v[x].size();i++)dfs(v[x][i]);
        long long t=k/a[x];
        int u=upper_bound(disc+1,disc+n+1,t)-disc-1;
        add(b[x],-1);
          ans+=query(u);
    }
    int main(){
        scanf("%d",&T);
        while(T--){
            memset(d,0,sizeof(d));
            memset(c,0,sizeof(c));
            for(int i=1;i<=n;i++)v[i].clear();
            scanf("%d%lld",&n,&k);
            for(int i=1;i<=n;i++)scanf("%lld",a+i),disc[i]=a[i];
            sort(disc+1,disc+n+1);
            for(int i=1;i<=n;i++)b[i]=remark(a[i]);
            for(int i=1;i<n;i++){
                int x,y;
                scanf("%d%d",&x,&y);
                v[x].push_back(y);
                d[y]++;
            }ans=0;
            for(int i=1;i<=n;i++)if(!d[i])dfs(i);
            printf("%d
    ",ans);
        }return 0;
    }
    

      

  • 相关阅读:
    [转]Eclipse之ANT使用
    [转]深入浅出解读微软云计算:让云触手可及
    [转]android的selector,背景选择器
    [转]android 个人铃声设置代码
    [转]Android中的Frame动画
    [转]WebGL中文教程
    节点遍历函数
    javascript深拷贝
    javascript 跨浏览器的事件系统
    CSS选择器的权重详解
  • 原文地址:https://www.cnblogs.com/forever97/p/hdu5877.html
Copyright © 2020-2023  润新知