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; }