[hdu 6191 Query on A Tree] 字典树启发式合并

[hdu 6191 Query on A Tree] 字典树启发式合并

分类:Data Structure Trie Tree

1. 题目链接

[hdu 6191 Query on A Tree]

2. 题意描述

有一个棵 n 个节点的树,每个节点上有一个权值。然后是,q个询问,每次查询包含两个数 u,x , 查询以 u 为根节点的子树中的所有节点的权值xor x <script type="math/tex" id="MathJax-Element-245">x</script>的最大值。

3. 解题思路

这题有两种思路:第一种方法是dfs序+可持久化字典树。
第二种方法是离线所有询问。然后对树进行后序dfs遍历的时候,启发式合并字典树,同时记录答案。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef long double lb;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ull, ull> puu;
typedef pair<lb, lb> pbb;
typedef vector<int> vi;

const int inf = 0x3f3f3f3f;
const ll infl = 0x3f3f3f3f3f3f3f3fLL;
template<typename T> inline void umax(T &a, T b) { a = max(a, b); }
template<typename T> inline void umin(T &a, T b) { a = min(a, b); }
template<typename T> inline T randIntv(const T& a, const T& b) { return (T)rand() % (b - a + 1) + a; }

const int MAXN = 100005;
struct Edge {
    int v, next;
} edge[MAXN];
int n, q, head[MAXN], tot;
ll w[MAXN];

void edge_init() {
    tot = 0;
    memset(head, -1, sizeof(head));
}
void edge_ins(int u, int v) {
    edge[tot] = Edge{v, head[u]};
    head[u] = tot ++;
}

struct Trie {
    static const int BITS = 40;
    static const int null = 0;
    struct TNode {
        int ch[2];
        void I() { ch[0] = ch[1] = 0; }
    } node[MAXN * 50];
    int root[MAXN], tot;
    void init() {
        node[tot = 0].I();
    }
    int new_node() {
        node[++ tot].I();
        return tot;
    }
    void ins(int u, const ll x) {
        int pos = root[u] = new_node();
        for (ll i = BITS - 1; i >= 0; --i) {
            ll j = (x >> i) & 1;
            if (node[pos].ch[j] == null) node[pos].ch[j] = new_node();
            pos = node[pos].ch[j];
        }
    }
    int merge(const int u, const int v) {
        if (u == null) return v;
        if (v == null) return u;
        node[u].ch[0] = merge(node[u].ch[0], node[v].ch[0]);
        node[u].ch[1] = merge(node[u].ch[1], node[v].ch[1]);
        return u;
    }
    ll query(const int u, const ll x) {
        ll ret = 0; int pos = root[u];
        for (ll i = BITS - 1; i >= 0; --i) {
            ll j = (x >> i) & 1;
            if (node[pos].ch[j ^ 1] != null) {
                pos = node[pos].ch[j ^ 1];
                ret = ret << 1ll | 1ll;
            } else {
                pos = node[pos].ch[j];
                ret = ret << 1ll;
            }
            assert(pos != null);
        }
        return ret;
    }
} trie;

vector<pll> qr[MAXN];
ll res[MAXN];

void dfs(int u, int fa) {
    trie.ins(u, w[u]);
    for (int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].v;
        if (v == fa) continue;
        dfs(v, u);
        trie.merge(trie.root[u], trie.root[v]);
    }
    for (auto &e : qr[u]) {
        res[e.first] = trie.query(u, e.second);
    }
}

int main() {
#ifdef ___LOCAL_WONZY___
    freopen ("input.txt", "r", stdin);
#endif // ___LOCAL_WONZY___
    while (~scanf("%d %d", &n, &q)) {
        for (int i = 1; i <= n; ++i) {
            scanf("%lld", &w[i]);
        }
        edge_init();
        for (int i = 2; i <= n; ++i) {
            int fa; scanf("%d", &fa);
            edge_ins(fa, i);
        }
        trie.init();
        for (int i = 1; i <= q; ++i) {
            int u; ll x; scanf("%d %lld", &u, &x);
            qr[u].push_back(pll(i, x));
        }
        dfs(1, 1);
        for (int i = 1; i <= q; ++i) {
            printf("%lld\n", res[i]);
        }
        for (int i = 1; i <= n; ++i) qr[i].clear();
    }
#ifdef ___LOCAL_WONZY___
    cout << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC * 1000 << " ms." << endl;
#endif // ___LOCAL_WONZY___
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值