hdu4605

hdu4605

题意

给出一棵带权值的树,多个查询 \(v, X\),某个重量为 \(X\) 的小球从根结点出发,根据 \(X\) 与当前结点权值的大小关系决定走左右子结点的概率,问到达 \(v\) 结点的概率。

分析

先离散化,再树状数组维护路径上结点的值,查询离线处理。

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 5;
int l[MAXN], r[MAXN], c[MAXN];
vector<int> v1[MAXN], v2[MAXN];
int x[MAXN], y[MAXN], d[MAXN << 1];
int f[2][MAXN];
void update(int p, int k, int z) {
    while(k < MAXN) {
        f[p][k] += z;
        k += k & -k;
    }
}
int query(int p, int k) {
    int a = 0;
    while(k) {
        a += f[p][k];
        k -= k & -k;
    }
    return a;
}
void dfs(int u) {
    for(int i = 0; i < v1[u].size(); i++) {
        int a = v2[u][i], b = v1[u][i];
        if((u != 1 && a == c[1]) || query(0, a) - query(0, a - 1) > 0 || query(1, a) - query(1, a - 1) > 0) x[b] = -1;
        else {
            int cnt01 = query(0, a - 1), cnt00 = query(0, MAXN - 1) - query(0, a);
            int cnt11 = query(1, a - 1), cnt10 = query(1, MAXN - 1) - query(1, a);
            y[b] = cnt00 + cnt10 + 3 * (cnt01 + cnt11);
            x[b] = cnt11;
        }
    }
    if(l[u]) {
        update(0, c[u], 1);
        dfs(l[u]);
        update(0, c[u], -1);
        update(1, c[u], 1);
        dfs(r[u]);
        update(1, c[u], -1);
    }
}
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        memset(l, 0, sizeof l);
        memset(f, 0, sizeof f);
        int n, m;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            v1[i].clear();
            v2[i].clear();
            scanf("%d", &c[i]);
            d[i] = c[i];
        }
        scanf("%d", &m);
        while(m--) {
            int u, a, b;
            scanf("%d%d%d", &u, &a, &b);
            l[u] = a;
            r[u] = b;
        }
        int q;
        scanf("%d", &q);
        int cnt = n;
        for(int i = 0; i < q; i++) {
            int a, b;
            scanf("%d%d", &a, &b);
            v1[a].push_back(i);
            v2[a].push_back(b);
            d[++cnt] = b;
        }
        sort(d + 1, d + 1 + cnt);
        int nn = unique(d + 1, d + 1 + cnt) - d - 1;
        for(int i = 1; i <= n; i++) {
            c[i] = lower_bound(d + 1, d + 1 + nn, c[i]) - d;
            for(int j = 0; j < v2[i].size(); j++) v2[i][j] = lower_bound(d + 1, d + 1 + nn, v2[i][j]) - d;
        }
        dfs(1);
        for(int i = 0; i < q; i++) {
            if(x[i] == -1) printf("0\n");
            else printf("%d %d\n", x[i], y[i]);
        }
    }
    return 0;
}
posted @ 2017-10-28 18:31  ftae  阅读(158)  评论(0编辑  收藏  举报