HDU6191Query on A Tree(01字典树)

http://acm.hdu.edu.cn/showproblem.php?pid=6191

题意:给出一棵树,每一个结点有一个值,然后给出q个询问,每一个询问给出一个u和x,问u子树的权值与x的xor值最大。

做法:就使用01字典树,把询问都离线处理,然后dfs遍历这棵树,从叶子开始往上合并字典树,字典树的合并也很简单,直接接上就可以了,重复的,删除一个就可以了,编程难度不是很大。

#include "bits/stdc++.h"

using namespace std;
const double eps = 1e-8;
#define lowbit(x) x&-x
#define pll pair<ll,ll>
#define pii pair<int,int>
#define fi first
#define se second
#define makp make_pair

int dcmp(double x) {
    if (fabs(x) < eps) return 0;
    return (x > 0) ? 1 : -1;
}

typedef long long ll;
typedef unsigned long long ull;
const ull hash1 = 201326611;
const ull hash2 = 50331653;
const int N = 100000 + 10;
const int M = 2048 + 10;
const int inf = 0x3f3f3f3f;
const ll mod = 1000000000 + 7;
vector<int> g[N];
int n, q, val[N], ans[N];
vector<pii > p[N];
int root[N], nxt[N * 35][2], tot = 0;

void Insert(int x, int rt) {
    int u = rt;
    for (int i = 31; i >= 0; i--) {
        int idx = (x >> i) & 1;
        if (nxt[u][idx] == 0) nxt[u][idx] = ++tot;
        u = nxt[u][idx];
    }
}

int query(int x, int rt) {
    int ans = 0, u = rt;
    for (int i = 31; i >= 0; i--) {
        int idx = (x >> i) & 1;
        if (nxt[u][idx ^ 1] != 0) {
            u = nxt[u][idx ^ 1];
            ans |= (1 << i);
        } else u = nxt[u][idx];
    }
    return ans;
}

int Union(int rt1, int &rt2) {
    if (rt1 == 0) return rt2;
    if (rt2 == 0) return rt1;
    nxt[rt1][0] = Union(nxt[rt1][0], nxt[rt2][0]);
    nxt[rt1][1] = Union(nxt[rt1][1], nxt[rt2][1]);
    rt2 = 0;
    return rt1;
}

void dfs(int u) {
    ///root[u] = ++tot;
    Insert(val[u], root[u]);
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        dfs(v);
        root[u] = Union(root[u], root[v]);
    }
    for (auto i:p[u]) {
        ans[i.fi] = query(i.se, root[u]);
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    while (cin >> n >> q) {
        for (int i = 0; i <= n; i++) {
            g[i].clear();
            p[i].clear();
        }
        memset(nxt, 0, sizeof(nxt));
        ///memset(root, 0, sizeof(root));
        tot = n;
        int u, v;
        for (int i = 1; i <= n; i++) {
            cin >> val[i];
            root[i] = i;
        }
        for (int i = 2; i <= n; i++) {
            cin >> u;
            g[u].push_back(i);
        }
        for (int i = 1; i <= q; i++) {
            cin >> u >> v;
            p[u].push_back(makp(i, v));
        }
        dfs(1);
        for (int i = 1; i <= q; i++) {
            cout << ans[i] << endl;
        }
    }
    return 0;
}
发布了130 篇原创文章 · 获赞 80 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/KXL5180/article/details/96560917
今日推荐