题目链接: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
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;
}