zoukankan      html  css  js  c++  java
  • HDU4757--Tree 可持久化trie + LCA

    题意:n个点的树,Q次询问,询问u-v路径上的点的权值与z抑或的最大值。

    先考虑,在一个区间上的问题,可以先建一个可持久化的Trie,然后每次询问,就和线段树的操作差不多,从最高位开始考虑选1还是选0。

    在树上的话, 可以转化成 parent[LCA(u, v)] - u ,  parent[LCA(u, v)] - v,这两个区间的最大值。

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 1e5 + 5;
    const int maxdep = 20;
    const int maxlog = 50;
    vector <int> G[maxn];
    int idx, A[maxn];
    //可持久化Trie, 初始状态val为0
    int tree[maxn], lson[maxn * maxlog], rson[maxn * maxlog], val[maxn * maxlog];
    int insert(int root, int x){              // x为每次插入的值
        int newroot = idx++;
        int tmp = newroot;
        for (int i = 19; i >= 0; i--){
            if (!(x & (1 << i))){
                lson[newroot] = idx++;
                rson[newroot] = rson[root];
                newroot = lson[newroot];
                root = lson[root];
            }else{
                rson[newroot] = idx++;
                lson[newroot] =lson[root];
                newroot = rson[newroot];
                root = rson[root];
            }
            val[newroot] = val[root] + 1;
        }
        return tmp;
    }
    int query (int ua, int ub, int z, int d){
        if (d == -1){
            return 0;
        }
        int res = 0;
        if (z & (1 << d)){
            if (val[lson[ub]] - val[lson[ua]]){
                res ^= 1 << d;
                res += query(lson[ua], lson[ub], z, d-1);
            }else{
                res = query(rson[ua], rson[ub], z, d-1);
            }
        }else{
            if (val[rson[ub]] - val[rson[ua]]){
                res ^= 1 << d;
                res += query(rson[ua], rson[ub],z, d-1);
            }else{
                res = query(lson[ua], lson[ub], z, d-1);
            }
        }
        return res;
    }
    int parent[maxdep][maxn], dep[maxn];
    void dfs(int u, int father){
        parent[0][u] = father;
        dep[u] = dep[father] + 1;
        tree[u] = insert(tree[father], A[u]);
        for (int v: G[u]){
            if (v != father){
                dfs(v, u);
            }
        }
    }
    void lca_init(int n){
        dfs(1, 0);
        for (int k = 0; k + 1 < maxdep; k++){
            for (int v = 1; v <= n; v++){
                if (parent[0][v] <= 0){
                    parent[k+1][v] = -1;
                }else{
                    parent[k+1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }
    int lca(int u, int v){
        if (dep[u] > dep[v]){
            swap(u, v);
        }
        for (int k = 0; k < maxdep; k++){
            if ((dep[v] - dep[u]) >> k & 1){
                v = parent[k][v];
            }
        }
        if (u == v){
            return u;
        }
        for (int k = maxdep-1; k >= 0; k--){
            if (parent[k][u] != parent[k][v]){
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }
    void init(){
        for (int i = 0; i < maxn; i++){
            G[i].clear();
        }
        idx = 0;
        memset(val, 0, sizeof (val));
    }
    void debug(int x, int i){
        if (val[lson[x]]){
            printf("%d,0 ", i);
            debug(lson[x], i-1);
        }
    
        if (val[rson[x]]){
            printf("%d,1 ", i);
            debug(rson[x], i-1);
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt", "r", stdin);
        #endif // ONLINE_JUDGE
        int n, m;
        while (~ scanf ("%d%d", &n, &m)){
            init();
            for (int i = 1; i <= n; i++){
                scanf ("%d", A+i);
            }
            for (int i = 0; i < n-1; i++){
                int u, v;
                scanf ("%d%d", &u, &v);
                G[u].push_back(v);
                G[v].push_back(u);
            }
            dfs(1, 0);
            lca_init(n);
            for (int i = 0; i < m; i++){
                int u, v, c;
                scanf ("%d%d%d", &u, &v, &c);
                int tmp = parent[0][lca(u, v)];
                printf("%d
    ", max(query(tree[tmp], tree[u], c, 19), query(tree[tmp], tree[v], c, 19)));
            }
        }
        return 0;
    }
  • 相关阅读:
    推销员问题
    string类实现
    链表倒数第k个节点
    设计模式之单例模式大全
    空类 sizeof 为什么是1
    类的三种继承方式
    单例模式典型创建方法(三种)
    虚函数实现
    链表删除结点
    TCP的状态转移
  • 原文地址:https://www.cnblogs.com/oneshot/p/4832858.html
Copyright © 2011-2022 走看看