HDU-6191【可持续化字典树+DFS序】

传送门
和主席树的思路差不多,用前缀和的思想保存n颗字典树(当然要动态开点),用对第i颗字典树上的节点sum[j][0/1]表示前i颗树第j位0/1的个数。对于询问只需要按位贪心就行了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 100;
int out[maxn], cc[maxn], id[maxn], val[maxn];
int root[maxn];
vector<int> G[maxn];
int cnt;
int n, q, m;
void dfs(int u, int fa) {
    id[u] = ++cnt;
    val[cnt] = u;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v != fa) dfs(v, u);
    }
    out[u] = cnt;
}
struct Trie {
    int nex[maxn<<5][2], tot, sum[maxn<<5][2];
    int newnode() {
        nex[tot][0] = nex[tot][1] = 0;
        return tot++;
    }
    void init() {
        tot = 1;
        nex[0][0] = nex[0][1] = 0;
    }
    int insert(int x, int id) {
        int t = newnode(), res = t;
        for (int i = 30; i >= 0; i--) {
            int tx = (1<<i)&x;
            tx = (tx>>i);
            sum[t][tx] = sum[id][tx]+1;
            sum[t][!tx] = sum[id][!tx];
            nex[t][tx] = newnode();
            nex[t][!tx] = nex[id][!tx];
            t = nex[t][tx];
            id = nex[id][tx];
        }
        return res;
    }
    int query(int x, int y, int s) {
        int res = 0;
        for(int i = 30; i >= 0; i--) {
            int t = (1<<i)&s;
            t = (t>>i);
            if(sum[y][!t]-sum[x][!t]) {
                res += (1<<i);
                x = nex[x][!t];
                y = nex[y][!t];
            }
            else {
                x = nex[x][t];
                y = nex[y][t];
            }
        }
        return res;
    }
} trie;
void init() {
    cnt = 0;
    root[0] = 0;
    for (int i = 0; i <= n; i++) G[i].clear();
}
int main() {
    freopen("in.txt", "r", stdin);
    while (scanf("%d%d", &n, &q) == 2) {
        init();
        trie.init();
        for (int i = 1; i <= n; i++) {
            scanf("%d", &cc[i]);
        }
        for (int i = 1; i < n; i++) {
            int f;
            scanf("%d", &f);
            G[f].push_back(i+1);
            G[i+1].push_back(f);
        }
        dfs(1, 0);
        for (int i = 1; i <= n; i++) {
            root[i] = trie.insert(cc[val[i]], root[i-1]);
        }
        for (int i = 1; i <= q; i++) {
            int u, x;
            scanf("%d%d", &u, &x);
            printf("%d\n", trie.query(root[id[u]-1], root[out[u]], x));
        }
  }
  return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39921637/article/details/89388211
今日推荐