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\n", max(query(tree[tmp], tree[u], c, 19), query(tree[tmp], tree[v], c, 19)));
        }
    }
    return 0;
}

 

posted @ 2015-09-23 17:16  PlasticSpirit  阅读(271)  评论(0编辑  收藏  举报