HDU 5877(Problem 1010) (DFS+树状数组+离散化)

来源:互联网 发布:能飞英语口语软件 编辑:程序博客网 时间:2024/05/17 01:37

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

题意:给定一颗树,然后对于每一个节点,找到它的任何一个祖先u,如果num[u] * num[v] <= k。则贡献加1

题解:dfs搜索一遍树结构,树状数组记录路径上的数信息,由于数太大,所以需要离散化一下

#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <cstdlib>#include <algorithm>#include <cmath>#include <vector>#include <set>#include <list>#include <queue>#include <map>#include <bitset>using namespace std;#define L(i) i<<1#define R(i) i<<1|1#define INF  0x3f3f3f3f#define pi acos(-1.0)#define eps 1e-3#define maxn 300100#define MOD 1000000007struct Edge{    int to,next;}edge[maxn];int tot,head[maxn];int n,m;int pre[maxn],num1[maxn],num2[maxn];long long k;long long a[maxn];long long b[maxn],ans;int c[maxn];void update(int x,int num) //离散化函数{    while(x <= maxn)    {       c[x] += num;       x += x&(-x);    }}int getsum(int x){    int s = 0;    while(x)    {        s += c[x];        x -= x&(-x);    }    return s;}void add_edge(int u,int v){    edge[tot].to = v;    edge[tot].next = head[u];    head[u] = tot++;}void dfs(int u){    //printf("%d\n",u);    update(num2[u],1);    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].to;        dfs(v);        //printf("%d\n",u);    }    //printf("%d\n",u);    update(num2[u],-1);    ans += getsum(num1[u]);    //printf("%d %lld\n",u,ans);}int main(){    int t,C = 1;    scanf("%d",&t);    while(t--)    {        tot = 0;        memset(head,-1,sizeof(head));        memset(pre,-1,sizeof(pre));        memset(c,0,sizeof(c));        scanf("%d%lld",&n,&k);        for(int i = 1; i <= n; i++)        {            scanf("%lld",&a[i]);            b[2*i-2] = a[i];            b[2*i-1] = k/a[i];        }        sort(b,b+2*n);        m = unique(b,b+2*n) - b;        for(int i = 1; i <= n; i++)        {            num1[i] = lower_bound(b,b+m,k/a[i]) - b+1;            num2[i] = lower_bound(b,b+m,a[i]) - b+1;        }        for(int i = 0; i < n-1; i++)        {            int x,y;            scanf("%d%d",&x,&y);            pre[y] = x;            add_edge(x,y);        }        int s;        for(int i = 1; i <= n; i++)            if(pre[i] == -1)                s = i;        ans = 0;        dfs(s);        printf("%lld\n",ans);    }    return 0;}
0 0
原创粉丝点击