HDU 4605 主席树

来源:互联网 发布:can数据帧格式 编辑:程序博客网 时间:2024/05/18 03:06

题意:

题目链接:http://acm.split.hdu.edu.cn/submit.php?pid=4605
一棵二叉树,根节点为1,每个节点都有一个权值,给出q个询问,每次询问给出v和x,问数字x从根节点落下,到节点v的概率是多少。
其中数x假如到达一个节点u:
1. 如果x==w[u],则x留在该节点。
2. 如果x>w[u],则x有1/8概率往左子树走,有7/8概率往右子树走。
3. 如果x>w[u],则x有1/2概率往左子树走,有1/2概率往右子树走。


思路:

主席树,要知道最后的答案,只要知道在从根到v的路径中,有多少数比x小,而且要分向左走和向右走分别有多少个点比x小。
根据树的结构建立主席树,每次在父亲的版本上建立新的线段树。树上要保存两个权值,一个是向左走的,一个是向右走的。
因为一个m写成了n,T了一万年。


代码:

#include <bits/stdc++.h>using namespace std;const int MAXN = 1e5 + 10;struct node {    int ls, rs, sum[2];} ns[MAXN * 20];int rt[MAXN], ct;void build(int& now, int l, int r) {    now = ++ct;    ns[now].sum[0] = ns[now].sum[1] = 0;    if (l == r) return;    int m = (l + r) >> 1;    build(ns[now].ls, l, m);    build(ns[now].rs, m + 1, r);}void update(int& now, int old, int l, int r, int x, int y) {    now = ++ct;    ns[now] = ns[old];    if (l == r) {        ns[now].sum[y]++;        return;    }    int m = (l + r) >> 1;    if (x <= m) update(ns[now].ls, ns[old].ls, l, m, x, y);    else update(ns[now].rs, ns[old].rs, m + 1, r, x, y);    ns[now].sum[y] = ns[ns[now].ls].sum[y] + ns[ns[now].rs].sum[y];}int query(int now, int old, int l, int r, int L, int R, int y) {    if (L <= l && r <= R) return ns[now].sum[y] - ns[old].sum[y];    int m = (l + r) >> 1, res = 0;    if (L <= m) res += query(ns[now].ls, ns[old].ls, l, m, L, R, y);    if (R > m) res += query(ns[now].rs, ns[old].rs, m + 1, r, L, R, y);    return res;}int n, t, m;int in[MAXN], a[MAXN], b[MAXN], dis[MAXN];struct Node {    int l, r;} tree[MAXN];void dfs(int u, int d) {    int l = tree[u].l, r = tree[u].r;    dis[u] = d;    int gg = lower_bound(b + 1, b + 1 + n, a[u]) - b;    if (l != -1) {        update(rt[l], rt[u], 1, n, gg, 0);        dfs(l, d + 1);    }    if (r != -1) {        update(rt[r], rt[u], 1, n, gg, 1);        dfs(r, d + 1);    }}int main() {    //freopen("in.txt", "r", stdin);    int T;    scanf("%d", &T);    while (T--) {        scanf("%d", &n);        for (int i = 1; i <= n; i++) {            scanf("%d", &a[i]);            tree[i].l = tree[i].r = -1;            b[i] = a[i];        }        sort (b + 1, b + 1 + n);        //n = unique(b + 1, b + 1 + n) - b - 1;        scanf("%d", &t);        for (int i = 1; i <= t; i++) {            int u, ls, rs;            scanf("%d%d%d", &u, &ls, &rs);            tree[u].l = ls; tree[u].r = rs;        }        scanf("%d", &m);        ct = 0;        build(rt[1], 1, n);        dfs(1, 0);        for (int i = 1; i <= m; i++) {            int v, x;            scanf("%d%d", &v, &x);            int xx = lower_bound(b + 1, b + 1 + n, x) - b;            if (b[xx] == x) {                int t1 = query(rt[v], rt[1], 1, n, xx, xx, 0);                if (t1 > 0) {                    puts("0");                    continue;                }                int t2 = query(rt[v], rt[1], 1, n, xx, xx, 1);                if (t2 > 0) {                    puts("0");                    continue;                }            }            if (xx > n || b[xx] > x) --xx;            int lnum = xx >= 1 ? query(rt[v], rt[1], 1, n, 1, xx, 0) : 0;            int rnum = xx >= 1 ? query(rt[v], rt[1], 1, n, 1, xx, 1) : 0;            int ansx = rnum, ansy = lnum * 3 + rnum * 3 + (dis[v] - rnum - lnum);            printf("%d %d\n", ansx, ansy);        }    }    return 0;}
原创粉丝点击