hdu5877(dfs序,树状数组,2016年大连站网络赛1010)

来源:互联网 发布:软件安全检测平台 编辑:程序博客网 时间:2024/06/05 16:07

题目链接

题目大意:
给一棵有根树,让你求这样的(u,v)满足
1)u是v的祖先
2)a[u] * a[v] <= k 两个条件。
求pair的数量。

题目解析:
首先我们可以很快的yy出要用dfs序,把树展成链,因为这是节点与子树中的节点的关系的问题,再想出对于一个节点u,那么只要找到[pre[u]+1,suf[u]1] 中小于等于k/a[u]的点的个数。仔细思考一下,如果我们从对应的val从大到小考虑u,那么k/a[u] 就是从小到大,那么可以在树状数组上更新然后统计,详细见代码,应该还是很好理解的。

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <vector>using namespace std;int n;long long k;const int maxn = 1e5 + 5;int a[maxn];int deg[maxn];int root;vector<int> G[maxn];int dfs_clock;int c[maxn << 1];int pre[maxn],suf[maxn];void init(int n){    for(int i = 1;i <= n;i++) G[i].clear();    dfs_clock = 0;    for(int i = 1;i <= n;i++) deg[i] = 0;    memset(c,0,sizeof(c));}void add(int x){    int up = maxn << 1;    while(x < up){        c[x]++;        x += x & -x;    }}int sum(int x){    int ret = 0;    while(x > 0){        ret += c[x];        x -= x & -x;    }    return ret;}void dfs(int u,int fa){    pre[u] = ++dfs_clock;    for(int i = 0;i < G[u].size();i++){        int v = G[u][i];        if(v == fa) continue;        dfs(v,u);    }    suf[u] = ++dfs_clock;}struct st{    int id,val;    bool operator < (const st & rhs) const{        return val < rhs.val;    }}s[maxn];typedef long long ll;int main(int argc, const char * argv[]) {    int T;    cin >> T;    while(T--){        scanf("%d",&n);        cin >> k;        init(n);        for(int i = 1;i <= n;i++) scanf("%d",&a[i]),s[i].id = i,s[i].val = a[i];        for(int i = 1;i < n;i++){            int u,v;            scanf("%d%d",&u,&v);            deg[v]++;            G[u].push_back(v);            G[v].push_back(u);        }        for(int i = 1;i <= n;i++){            if(deg[i] == 0){                root = i;                break;            }        }        dfs(root,-1);        sort(s + 1,s + 1 + n);        int front = 1;        ll ans = 0;        for(int i = n;i >= 1;i--){            ll tmp = k / (ll) s[i].val;            while(s[front].val <= tmp && front <= n){                add(pre[s[front].id]);                add(suf[s[front].id]);                front++;            }            ans += sum(suf[s[i].id] - 1) - sum(pre[s[i].id]);        }        cout << ans / 2 << endl;    }    return 0;}
0 0
原创粉丝点击