码迷,mamicode.com
首页 > 其他好文 > 详细

SCUT - 106 - 花式ac - 主席树

时间:2019-08-09 01:12:44      阅读:75      评论:0      收藏:0      [点我收藏+]

标签:--   stdin   查询   ret   print   build   离散化   ifd   pen   

https://scut.online/p/106

错在这组样例,发现是离散化之后,对k访问的时候也是应该访问离散化之后的k。

12 4
1 1 2 2 5 5 4 4 3 3 2
1 1 3 3 5 7 7 9 9 9 11 11
1 10
3 10
3 11
2 4

发现主席树大概还真的要开够log倍,少一点都不行,那干脆开大一点。

#include<bits/stdc++.h>
#define mid ((l+r)>>1)
using namespace std;

const int MAXN = 100000 + 5;

int a[MAXN], b[MAXN];
vector<int> E[MAXN];

int siz[MAXN], tid[MAXN], rnk[MAXN], cnt;

int T[MAXN], tcnt;
int sum[MAXN << 5], L[MAXN << 5], R[MAXN << 5];

void init(int n) {
    for(int i = 1; i <= n; ++i)
        E[i].clear();
    cnt = 0;
    tcnt = 0;
}

void dfs(int u) {
    siz[u] = 1;
    tid[u] = ++cnt;
    rnk[cnt] = u;
    for(auto v : E[u]) {
        dfs(v);
        siz[u] += siz[v];
    }
}

inline int build(int l, int r) {
    int rt = ++tcnt;
    sum[rt] = 0;
    if(l < r) {
        L[rt] = build(l, mid);
        R[rt] = build(mid + 1, r);
    }
    return rt;
}

inline int update(int pre, int l, int r, int x) {
    int rt = ++tcnt;
    R[rt] = R[pre];
    L[rt] = L[pre];
    sum[rt] = sum[pre] + 1;
    if(l < r) {
        if(x <= mid)
            L[rt] = update(L[pre], l, mid, x);
        else
            R[rt] = update(R[pre], mid + 1, r, x);
    }
    return rt;
}

//查询[u-1,v]中不超过k的数的个数
inline int query2(int u, int v, int l, int r, int k) {
    int res = 0;
    while(l < r && k < r) {
        if(k >= mid) {
            res += sum[L[v]] - sum[L[u]];
            u = R[u], v = R[v], l = mid + 1;
        } else
            u = L[u], v = L[v], r = mid;
    }
    return res + (k >= l ? sum[v] - sum[u] : 0);
}

int main() {
#ifdef Yinku
    freopen("Yinku.in", "r", stdin);
#endif // Yinku
    int n, q, r = 1;
    while(~scanf("%d%d", &n, &q)) {
        init(n);
        for(int i = 2, f; i <= n; ++i) {
            scanf("%d", &f);
            E[f].push_back(i);
        }
        dfs(r);
        for(int i = 1; i <= n; i ++) {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        sort(b + 1, b + 1 + n);
        int cb = unique(b + 1, b + 1 + n) - b - 1;
        tcnt = 0;
        T[0] = build(1, cb);
        for(int i = 1; i <= n; i ++) {
            int t = lower_bound(b + 1, b + 1 + cb, a[rnk[i]]) - b;
            T[i] = update(T[i - 1], 1, cb, t);
        }
        while(q--) {
            int u, k;
            scanf("%d%d", &u, &k);
            k = upper_bound(b + 1, b + 1 + cb, k) - b - 1;
            int l = tid[u], r = tid[u] + siz[u] - 1;
            printf("%d\n", query2(T[l - 1], T[r], 1, cb, k));
        }
    }
    return 0;
}

SCUT - 106 - 花式ac - 主席树

标签:--   stdin   查询   ret   print   build   离散化   ifd   pen   

原文地址:https://www.cnblogs.com/Yinku/p/11324761.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!