HDU 5877 Weak Pair (dfs 树状数组 || dfs序 主席树)

来源:互联网 发布:淘宝买gtx1080截图 编辑:程序博客网 时间:2024/06/05 16:16

题意:给你一颗树,每个节点有一个权值,给你一个k,问你满足a[u]*a[v] <= k的个数。(u是v的祖先)


思路:做的时候看到u和v又是子树关系,想当然就是dfs序啦,然后变成a[v]<=k/a[u], 这样枚举每一个节点u,计算子

树中<=k/a[u]的节点个数,这一步可以用主席树求(类似于:点开),所以直接敲了dfs序+主席树。。


其实这题有简单做法,我们可以在dfs整棵树过程中计算每个点作为儿子节点的贡献,

贡献即为其祖先节点u, k/a[u] >= a[v]的个数。

因此可以用树状数组维护从根节点开始的k/ai值,遍历到某个节点时将该节点加入BIT,遍历结束时从BIT中删除,这

对于每个节点,BIT中存的都是他的祖先。


因为数据比较大,所以离散化是必须的。


树状数组代码:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 2e5+5;ll a[maxn], Hash[maxn], k, ans;vector<int> g[maxn];int n, d, du[maxn], tree[maxn];int lowbit(int x){    return x&(-x);}void update(int pos, int val){    while(pos < maxn)    {        tree[pos] += val;        pos += lowbit(pos);    }}int query(int pos){    int res = 0;    while(pos)    {        res += tree[pos];        pos -= lowbit(pos);    }    return res;}void dfs(int u){    int x = lower_bound(Hash+1, Hash+1+d, a[u])-Hash;    ans += query(maxn-1)-query(x-1);    int y = lower_bound(Hash+1, Hash+1+d, k/a[u])-Hash;    update(y, 1);    for(int i = 0; i < g[u].size(); i++)    {        int v = g[u][i];        dfs(v);    }    update(y, -1);}int main(void){    int _;    cin >> _;    while(_--)    {        memset(tree, 0, sizeof(tree));        memset(du, 0, sizeof(du));        scanf("%d%lld", &n, &k);        for(int i = 0; i <= n; i++)            g[i].clear();        for(int i = 1; i <= n; i++)        {            scanf("%lld", &a[i]);            Hash[i] = a[i];            Hash[i+n] = k/a[i];        }        sort(Hash+1, Hash+1+2*n);        d = unique(Hash+1, Hash+1+2*n)-Hash-1;        for(int i = 1; i < n; i++)        {            int u, v;            scanf("%d%d", &u, &v);            g[u].push_back(v);            du[v]++;        }        int tRoot;        for(int i = 1; i <= n; i++)            if(!du[i])            {                tRoot = i;                break;            }        ans = 0;        dfs(tRoot);        printf("%lld\n", ans);    }    return 0;}



dfs序+主席树代码:

#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e5+5;vector<int> g[maxn];int n, a[maxn], in[maxn*4], out[maxn*4], fa[maxn*4], tot1, tot2;int lson[maxn<<5], rson[maxn<<5], sum[maxn<<5];int T[maxn], Hash[maxn];int cb[maxn], cur, d;ll k;int build(int l, int r){    int rt = ++tot2;    sum[rt] = 0;    if(l < r)    {        int mid = (l+r)/2;        lson[rt] = build(l, mid);        rson[rt] = build(mid+1, r);    }    return rt;}int update(int pre, int l, int r, int x){    int rt = ++tot2;    lson[rt] = lson[pre], rson[rt] = rson[pre], sum[rt] = sum[pre]+1;    if(l < r)    {        int mid = (l+r)/2;        if(x <= mid)            lson[rt] = update(lson[pre], l, mid, x);        else            rson[rt] = update(rson[pre], mid+1, r, x);    }    return rt;}int query(int u, int v, int l, int r, int k){    if(l >= r) return sum[v]-sum[u];    int mid = (l+r)/2;    int ans = 0;    if(k <= mid)        ans += query(lson[u], lson[v], l, mid, k);    else    {        ans += sum[lson[v]]-sum[lson[u]];        ans += query(rson[u], rson[v], mid+1, r, k);    }    return ans;}void dfs(int u, int pre){    int x = lower_bound(Hash+1, Hash+1+d, a[u])-Hash;    T[cur] = update(T[cur-1], 1, d, x);    cur++;    in[u] = ++tot1;    fa[u] = pre;    for(int i = 0; i < g[u].size(); i++)    {        int v = g[u][i];        if(v != pre)            dfs(v, u);    }    out[u] = tot1;}int main(void){    int _;    cin >> _;    while(_--)    {        tot1 = tot2 = 0;        memset(cb, 0, sizeof(cb));        for(int i = 0; i < maxn; i++)            g[i].clear();        scanf("%d%lld", &n, &k);        for(int i = 1; i <= n; i++)            scanf("%d", &a[i]), Hash[i] = a[i];        sort(Hash+1, Hash+1+n);        d = unique(Hash+1, Hash+1+n)-Hash-1;        T[0] = build(1, d);        for(int i = 1; i < n; i++)        {            int u, v;            scanf("%d%d", &u, &v);            g[u].push_back(v);            cb[v]++;        }        int tRoot;        for(int i = 1; i <= n; i++)            if(!cb[i])            {                tRoot = i;                break;            }        cur = 1;        dfs(tRoot, 0);        ll ans = 0;        for(int i = 1; i <= n; i++)        {            ll des = k/a[i];            int x = upper_bound(Hash+1, Hash+1+d, des)-Hash-1;            ans += query(T[in[i]], T[out[i]], 1, d, x);        }        printf("%lld\n", ans);    }    return 0;}



阅读全文
1 0
原创粉丝点击