SPOJ PT07J Query on a tree III(dfs序,主席树)

来源:互联网 发布:武功山 知乎 编辑:程序博客网 时间:2024/05/17 14:19

dfs序变为线性的序列,然后就是主席树区间第k大

#include <bits/stdc++.h>#include <iostream>#include <cstdio>#include <cmath>#include <cstring>#include <algorithm>using namespace std;#pragma comment(linxer, "/STACK:102400000,102400000")#define LL long long #define pii pair<int, int>#define MP make_pair#define ls i << 1#define rs ls | 1#define md (ll + rr >> 1)#define lson ll, md, ls#define rson md + 1, rr, rs#define mod 1000000007#define inf 0x3f3f3f3f#define N 100010#define M 200020int ch[N*20][2], sum[N*20], nam[N], rt[N], tot;int fst[N], vv[M], nxt[M], e;int dc, st[N], ed[N], lab[N];int san[N], cnt, val[N];int haxi(int v){    return lower_bound(san + 1, san + 1 + cnt, v) - san;}void init(){    memset(fst, -1, sizeof fst); e = 0;}void add(int u, int v){    vv[e] = v, nxt[e] = fst[u], fst[u] = e++;}void dfs(int u, int p){    st[u] = ++dc; lab[dc] = u;    for(int i = fst[u]; ~i; i = nxt[i]){        int v = vv[i];        if(v == p) continue;        dfs(v, u);    }    ed[u] = dc;}int update(int x, int v, int ll, int rr, int i){    int k = ++tot;    ch[k][0] = ch[i][0], ch[k][1] = ch[i][1];    sum[k] = sum[i] + 1;    if(ll == rr){        nam[ll] = v;        return k;    }    if(x <= md) ch[k][0] = update(x, v, ll, md, ch[i][0]);    else ch[k][1] = update(x, v, md + 1, rr, ch[i][1]);    return k;}int query(int l, int r, int ll, int rr, int k){    if(ll == rr) return nam[ll];    int tmp = sum[ch[r][0]] - sum[ch[l][0]];    if(tmp >= k)        return query(ch[l][0], ch[r][0], ll, md, k);    else return query(ch[l][1], ch[r][1], md + 1, rr, k - tmp);}int main(){    int n;    while(scanf("%d", &n) != EOF){        tot = cnt = 0;        memset(ch, 0, sizeof ch);        memset(sum, 0, sizeof sum);        init();        for(int i = 1; i <= n; ++i){            scanf("%d", &val[i]);            san[++cnt] = val[i];        }        sort(san + 1, san + 1 + cnt);        cnt = unique(san + 1, san + 1 + cnt) - san - 1;        for(int i = 1; i <= n; ++i)            val[i] = haxi(val[i]);        for(int i = 1; i < n; ++i){            int u, v;            scanf("%d%d", &u, &v);            add(u, v);            add(v, u);        }        dc = 0;        dfs(1, -1);        rt[0] = 0;        for(int i = 1; i <= n; ++i){            rt[i] = update(val[lab[i]], lab[i], 1, n, rt[i-1]);        }        int q;        scanf("%d", &q);        while(q--){            int L, R, u, k;            scanf("%d%d", &u, &k);            L = st[u], R = ed[u];            printf("%d\n", query(rt[L-1], rt[R], 1, n, k));        }    }    return 0;}
0 0