HDU 4757 Tree(可持久化字典树)(2013 ACM/ICPC Asia Regional Nanjing Online)

Problem Description
  Zero and One are good friends who always have fun with each other. This time, they decide to do something on a tree which is a kind of graph that there is only one path from node to node. First, Zero will give One an tree and every node in this tree has a value. Then, Zero will ask One a series of queries. Each query contains three parameters: x, y, z which mean that he want to know the maximum value produced by z xor each value on the path from node x to node y (include node x, node y). Unfortunately, One has no idea in this question. So he need you to solve it.
 
Input
  There are several test cases and the cases end with EOF. For each case:

  The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^5), which are the amount of tree’s nodes and queries, respectively.

  The second line contains n integers a[1..n] and a[i](0<=a[i]<2^{16}) is the value on the ith node.

  The next n–1 lines contains two integers u v, which means there is an connection between u and v.

  The next m lines contains three integers x y z, which are the parameters of Zero’s query.
 
Output
  For each query, output the answer.
 
题目大意:给你一颗n个点的树,每个点有一个权值。然后有m个询问,问从x到y的简单路径中,权值 xor z最大是多少。
思路:可持久化的0-1字典树,每个点在父节点的历史版本上新建一棵字典树,字典树上的每个结点给一个值记录从这个结点到树的根节点,有多少个权值会经过这个字典树上的结点。询问的时候在字典树上奏即可。由于a[i]<2^16,那么字典树的深度最大为16,空间复杂度为O(16 * n)。
PS:tarjan果然要比RMQ快啊。
PS2:数据保障z<2^16,虽然题目没讲……
 
代码(1265MS):
  1 #include <cstdio>

  2 #include <iostream>

  3 #include <algorithm>

  4 #include <cstring>

  5 using namespace std;

  6 

  7 const int MAX = 100010;

  8 const int MAXN = 2 * MAX;

  9 const int MAXE = 2 * MAXN;

 10 

 11 int head[MAXN], weight[MAXN], fa[MAX];

 12 bool vis[MAX];

 13 int to[MAXE], next[MAXE], id[MAXE];

 14 int n, m, ecnt;

 15 

 16 inline void init() {

 17     memset(head, 0, sizeof(head));

 18     memset(vis, 0, sizeof(vis));

 19     for(int i = 1; i <= n; ++i) fa[i] = i;

 20     ecnt = 2;

 21 }

 22 

 23 inline void add_edge(int u, int v, int i) {

 24     to[ecnt] = v; id[ecnt] = i; next[ecnt] = head[u]; head[u] = ecnt++;

 25     to[ecnt] = u; id[ecnt] = i; next[ecnt] = head[v]; head[v] = ecnt++;

 26 }

 27 

 28 struct QUERY {

 29     int x, y, lca, z;

 30     void read(int i) {

 31         scanf("%d%d%d", &x, &y, &z);

 32         add_edge(x + n, y + n, i);

 33     }

 34 } Query[MAX];

 35 

 36 int get_set(int x) {

 37     return fa[x] == x ? x : fa[x] = get_set(fa[x]);

 38 }

 39 

 40 void dfs_LCA(int u, int f) {

 41     for(int p = head[u]; p; p = next[p]) {

 42         int &v = to[p];

 43         if(v == f) continue;

 44         dfs_LCA(v, u);

 45         fa[v] = u;

 46     }

 47     vis[u] = true;

 48     for(int p = head[u + n]; p; p = next[p]) {

 49         int v = to[p] - n;

 50         if(vis[v]) Query[id[p]].lca = get_set(v);

 51     }

 52 }

 53 

 54 struct Node {

 55     int go[2], cnt;

 56 } tree[20 * MAX];

 57 int root[MAX], Tcnt;

 58 

 59 void init_tree() {

 60     Tcnt = 1; root[0] = 0;

 61 }

 62 

 63 int insert(int x, int val) {

 64     tree[Tcnt] = tree[x];

 65     int ret = x = Tcnt++;

 66     for(int i = 15; i >= 0; --i) {

 67         int idx = (val >> i) & 1, t = Tcnt++;

 68         tree[t] = tree[tree[x].go[idx]];

 69         ++tree[t].cnt;

 70         tree[x].go[idx] = t;

 71         x = t;

 72     }

 73     return ret;

 74 }

 75 

 76 void dfs_build(int u, int f) {

 77     root[u] = insert(root[f], weight[u]);

 78     for(int p = head[u]; p; p = next[p]) {

 79         int &v = to[p];

 80         if(v == f) continue;

 81         dfs_build(v, u);

 82     }

 83 }

 84 

 85 int query(int x, int y, int lca, int val) {

 86     int ret = 0, ret_lca = weight[lca] ^ val;

 87     x = root[x], y = root[y], lca = root[lca];

 88     for(int i = 15; i >= 0; --i) {

 89         int idx = !((val >> i) & 1);

 90         int cnt = tree[tree[x].go[idx]].cnt + tree[tree[y].go[idx]].cnt - 2 * tree[tree[lca].go[idx]].cnt;

 91         if(cnt > 0) ret |= (1 << i);

 92         else idx = !idx;

 93         x = tree[x].go[idx], y = tree[y].go[idx], lca = tree[lca].go[idx];

 94     }

 95     return max(ret, ret_lca);

 96 }

 97 

 98 int main() {

 99     while(scanf("%d%d", &n, &m) != EOF) {

100         for(int i = 1; i <= n; ++i) scanf("%d", &weight[i]);

101         init();

102         for(int i = 1; i < n; ++i) {

103             int u, v;

104             scanf("%d%d", &u, &v);

105             add_edge(u, v, 0);

106         }

107         for(int i = 1; i <= m; ++i) Query[i].read(i);

108         dfs_LCA(1, 0);

109         init_tree();

110         dfs_build(1, 0);

111         for(int i = 1; i <= m; ++i)

112             printf("%d\n", query(Query[i].x, Query[i].y, Query[i].lca, Query[i].z));

113     }

114 }
View Code

 

你可能感兴趣的:(online)