hdu 5877(树状数组+dfs)

Weak Pair

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2387    Accepted Submission(s): 740


Problem Description
You are given a rooted tree of N nodes, labeled from 1 to N. To the ith node a non-negative value ai is assigned.An ordered pair of nodes (u,v) is said to be weak if
  (1) u is an ancestor of v (Note: In this problem a node u is not considered an ancestor of itself);
  (2) au×avk.

Can you find the number of weak pairs in the tree?
 
Input
There are multiple cases in the data set.
  The first line of input contains an integer T denoting number of test cases.
  For each case, the first line contains two space-separated integers, N and k, respectively.
  The second line contains N space-separated integers, denoting a1 to aN.
  Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes u and v , where node u is the parent of node v.

  Constrains:
  
  1N105
  
  0ai109
  
  0k1018
 
Output
For each test case, print a single integer on a single line denoting the number of weak pairs in the tree.
 
Sample Input
1 2 3 1 2 1 2
 
Sample Output
1
 
Source
 
满足第一个条件的话进行DFS,然后统计父亲节点里面满足 val <= k/a[u] 的个数.这里可以用 树状数组进行维护.
///pro do this : a[l]%a[l+1]%...%a[r]
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <queue>
#include <string.h>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 200005;
const LL INF = 1e19;
LL a[N],b[N],c[N];
int cnt,n,m;
int indegree[N];
struct Edge{
    int v,next;
}edge[N];
int head[N],tot;
LL ans,k;
void addEdge(int u,int v,int &k){
    edge[k].v = v,edge[k].next = head[u],head[u] = k++;
}
void init(){
    tot = 0,ans = 0;
    memset(head,-1,sizeof(head));
    memset(indegree,0,sizeof(indegree));
    memset(c,0,sizeof(c));
}
int lowbit(int x){
    return x&(-x);
}
void update(int v,int idx){
    for(int i=idx;i<=cnt;i+=lowbit(i)){
        c[i] += v;
    }
}
LL getsum(int idx){
    LL ans=0;
    for(int i=idx;i>=1;i-=lowbit(i)){
        ans+=c[i];
    }
    return ans;
}
void dfs(int u){
    int x = upper_bound(b+1,b+cnt+1,k/a[u])-b-1; ///upper_bound 第一个大于当前元素的第一个数的下标.
    int pos = lower_bound(b+1,b+cnt+1,a[u])-b; ///寻找离散化之后的下标
    ans+=getsum(x);
    update(1,pos);
    for(int i=head[u];i!=-1;i=edge[i].next){
        dfs(edge[i].v);
    }
    update(-1,pos);
}
int main(){
    int tcase;
    scanf("%d",&tcase);
    while(tcase--){
        init();
        scanf("%d%lld",&n,&k);
        m = 0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            b[++m] = a[i];
            if(a[i]==0) b[++m] = INF;
            else b[++m] = k/a[i];
        }
        sort(b+1,b+m+1);
        cnt = unique(b+1,b+m+1)-(b+1);
        for(int i=1;i<n;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            addEdge(u,v,tot);
            indegree[v]++;
        }
        for(int i=1;i<=n;i++){
            if(indegree[i]==0) dfs(i);
        }
        printf("%lld
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/liyinggang/p/5877279.html