HDU 5877 Weak Pair(dfs + 树状数组 + 离散化)

来源:互联网 发布:软件测试管理体系 编辑:程序博客网 时间:2024/05/17 04:15

#include<cstdio>#include<cstring>#include<cmath>#include<map>#include<string>#include<stack>#include<vector>#include<queue>#include<set>#include<algorithm>#include<iostream>typedef long long ll;const int maxn = 1e5 + 10;const double eps = 1e-7;const ll INF = 1e18;using namespace std;ll C[maxn * 2], a[maxn * 2], b[maxn * 2];vector<int> G[maxn];int n, T, num, nn;ll k;int ch[maxn];ll res;void init() {    num = 0; res = 0;    for(int i = 0; i < maxn; i++)        G[i].clear();    memset(C, 0, sizeof(C));    memset(ch, 0, sizeof(ch));}ll sum(int ind) {    ll s = 0;    while(ind) {        s += C[ind]; ind -= ind & -ind;    }    return s;}void update(int ind, int add) {    while(ind <= nn) {        C[ind] += add; ind += ind & -ind;    }}void dfs(int u, int d) {    if(!a[u]) res += d;    else {        int ind = lower_bound(b, b + nn, k / a[u]) - b + 1;        res += sum(ind);    }    int c = lower_bound(b, b + nn, a[u]) - b + 1;    update(c, 1);    for(int i = 0; i < G[u].size(); i++) {        int v = G[u][i];        dfs(v, d + 1);    }    update(c, -1);}int main(){    scanf("%d", &T);    while(T--) {        init();        scanf("%d %lld", &n, &k);        for(int i = 1; i <= n; i++) {            scanf("%lld", &a[i]);            b[num++] = a[i];            if(a[i]) b[num++] = k / a[i];        }        sort(b, b + num);        nn = unique(b, b + num) - b;        for(int i = 1; i < n; i++) {            int f, t;            scanf("%d %d", &f, &t);            G[f].push_back(t);            ch[t] = 1;        }        int node;        for(int i = 1; i <= n; i++) {            if(!ch[i]) { node = i; break; }        }        dfs(node, 0);        printf("%lld\n", res);    }    return 0;}

题意:给出一棵树,求出a[u] * a[v] <= k的(u,v)的对数

思路:搜索过程中用树状数组更新同深度的值,一个节点只能从根节点由一条路而来,相当于在一条路径上用树状数组


0 0
原创粉丝点击