HDU5877 Weak Pair(树状数组+dfs)

来源:互联网 发布:淘宝哪家supreme复刻 编辑:程序博客网 时间:2024/06/05 05:24

Weak Pair

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


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 nodesu 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
12 31 21 2
 

Sample Output
1
 

Source
2016 ACM/ICPC Asia Regional Dalian Online
题意:有一棵树,N个结点,N-1条边,每个结点有权值ai,如果存在一个点对,由结点和它的祖先组成,
并且它们相乘的结果<=K,那么这个点对就称为weak,求有多少个这样的点对。
思路:先将ai和K/ai离散化,然后找到根节点遍历树,每插入一个结点前,用树状数组求当前小于K/ai的结点
有多少个并加入结果,然后再将树状数组ai的位置+1,每次回溯前将树状数组ai的位置-1。注意ai可能为0,所
以K/ai要处理一下。
#include <bits/stdc++.h>using namespace std;#define ll long long int#define maxn 100010ll bit[maxn*2], a[maxn], b[maxn*2], ans, K;int N, n, tot, head[maxn];bool vis[maxn];void add(ll bit[], int i, ll x){    while(i <= n){        bit[i] += x;        i += i&-i;    }}ll sum(ll bit[], int i){    ll s = 0;    while(i > 0){        s += bit[i];        i -= i&-i;    }    return s;}struct Edge{    int to, next;}edge[maxn];void addedge(int u, int v){    edge[tot].to = v;    edge[tot].next = head[u];    head[u] = tot++;}void dfs(int now){    vis[now] = 1;    //printf("%d ", now);    ll loc1, loc2;    if(a[now] == 0) loc1 = n;    else {        ll point = K/a[now];        //printf("%I64d ", point);        loc1 = lower_bound(b, b+n, point)-b+1;    }    loc2 = lower_bound(b, b+n, a[now])-b+1;    //printf("%I64d\n", sum(bit, loc1));    ans += sum(bit, loc1);    add(bit, loc2, 1);    for(int i = head[now];i != -1;i = edge[i].next){        int son = edge[i].to;        if(vis[son]) continue;        dfs(son);    }    add(bit, loc2, -1);}int main(){    int i, T, top;    scanf("%d", &T);    while(T--){        scanf("%d %I64d", &N, &K);        top = 0;        for(i = 1;i <= N;i++){            scanf("%I64d", &a[i]);            b[top++] = a[i];            if(a[i] != 0) b[top++] = K/a[i];        }        sort(b, b+top);        n = unique(b, b+top)-b;        int u, v;        memset(head, -1, sizeof head);        memset(bit, 0, sizeof bit);        memset(vis, 0, sizeof vis);        tot = 0;        ans = 0;        for(i = 0;i < N-1;i++){            scanf("%d %d", &u, &v);            addedge(u, v);            vis[v] = 1;        }        int start;        for(i = 1;i <= N;i++)            if(!vis[i]){                start = i;                break;            }        memset(vis, 0, sizeof vis);        dfs(start);        printf("%I64d\n", ans);    }}

 
0 0
原创粉丝点击