HDU6191(01字典树启发式合并)
Posted Penn000
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6191(01字典树启发式合并)相关的知识,希望对你有一定的参考价值。
Query on A Tree
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 801 Accepted Submission(s): 302
Problem Description
Monkey A lives on a tree, he always plays on this tree.
One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.
Monkey A gave a value to each node on the tree. And he was curious about a problem.
The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).
Can you help him?
One day, monkey A learned about one of the bit-operations, xor. He was keen of this interesting operation and wanted to practise it at once.
Monkey A gave a value to each node on the tree. And he was curious about a problem.
The problem is how large the xor result of number x and one node value of label y can be, when giving you a non-negative integer x and a node label u indicates that node y is in the subtree whose root is u(y can be equal to u).
Can you help him?
Input
There are no more than 6 test cases.
For each test case there are two positive integers n and q, indicate that the tree has n nodes and you need to answer q queries.
Then two lines follow.
The first line contains n non-negative integers V1,V2,?,Vn, indicating the value of node i.
The second line contains n-1 non-negative integers F1,F2,?Fn?1, Fi means the father of node i+1.
And then q lines follow.
In the i-th line, there are two integers u and x, indicating that the node you pick should be in the subtree of u, and x has been described in the problem.
2≤n,q≤105
0≤Vi≤109
1≤Fi≤n, the root of the tree is node 1.
1≤u≤n,0≤x≤109
For each test case there are two positive integers n and q, indicate that the tree has n nodes and you need to answer q queries.
Then two lines follow.
The first line contains n non-negative integers V1,V2,?,Vn, indicating the value of node i.
The second line contains n-1 non-negative integers F1,F2,?Fn?1, Fi means the father of node i+1.
And then q lines follow.
In the i-th line, there are two integers u and x, indicating that the node you pick should be in the subtree of u, and x has been described in the problem.
2≤n,q≤105
0≤Vi≤109
1≤Fi≤n, the root of the tree is node 1.
1≤u≤n,0≤x≤109
Output
For each query, just print an integer in a line indicating the largest result.
Sample Input
2 2
1 2
1
1 3
2 1
Sample Output
2
3
Source
题意:给一棵树,树上每个节点有一个权值。然后有q次查询,每次查询给你节点标号u和一个数x。问以u的子树里面的所有节点点权和数x的最大异或值是多少。
思路:使用01字典树解决异或值最大问题,使用字典树的合并,可得到每棵子树上的异或最大值。
1 //2017-09-16 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #include <vector> 7 8 using namespace std; 9 10 const int N = 110000; 11 int head[N], tot; 12 struct Edge{ 13 int v, next; 14 }edge[N]; 15 16 void init(){ 17 tot = 0; 18 memset(head, -1, sizeof(head)); 19 } 20 21 void add_edge(int u, int v){ 22 edge[tot].v = v; 23 edge[tot].next = head[u]; 24 head[u] = tot++; 25 } 26 27 int n, q, arr[N]; 28 int ans[N]; 29 vector< pair<int, int> > qy[N]; 30 struct Trie{ 31 Trie* next[2]; 32 }*root[N]; 33 34 void insert(Trie* rt, int x){ 35 for(int i = 31; i >= 0; i--){ 36 int idx = (x>>i)&1; 37 if(rt->next[idx] == NULL){ 38 Trie *tmp = new Trie(); 39 rt->next[idx] = tmp; 40 } 41 rt = rt->next[idx]; 42 } 43 } 44 45 int query(Trie* rt, int x){ 46 int ans = 0; 47 for(int i = 31; i >= 0; i--){ 48 int idx = (x>>i)&1; 49 if(rt->next[idx^1] != NULL){ 50 rt = rt->next[idx^1]; 51 ans |= (1<<i); 52 }else rt = rt->next[idx]; 53 } 54 return ans; 55 } 56 57 Trie* merge(Trie* p, Trie* q){ 58 if(p == NULL)return q; 59 if(q == NULL)return p; 60 p->next[0] = merge(p->next[0], q->next[0]); 61 p->next[1] = merge(p->next[1], q->next[1]); 62 free(q); 63 return p; 64 } 65 66 void dfs(int u, int fa){ 67 root[u] = new Trie(); 68 insert(root[u], arr[u]); 69 for(int i = head[u]; i != -1; i = edge[i].next){ 70 int v = edge[i].v; 71 if(v == fa)continue; 72 dfs(v, u); 73 root[u] = merge(root[u], root[v]); 74 } 75 for(auto &q: qy[u]){ 76 ans[q.first] = query(root[u], q.second); 77 } 78 } 79 80 void clear(Trie* rt){ 81 if(rt->next[0]) clear(rt->next[0]); 82 if(rt->next[1]) clear(rt->next[1]); 83 free(rt); 84 } 85 86 int main() 87 { 88 while(scanf("%d%d", &n, &q) != EOF){ 89 init(); 90 for(int i = 1; i <= n; i++){ 91 scanf("%d", &arr[i]); 92 qy[i].clear(); 93 } 94 int v; 95 for(int i = 2; i <= n; i++){ 96 scanf("%d", &v); 97 add_edge(v, i); 98 } 99 int u, x; 100 for(int i = 0; i < q; i++){ 101 scanf("%d%d", &u, &x); 102 qy[u].push_back(make_pair(i, x)); 103 } 104 dfs(1, -1); 105 for(int i = 0; i < q; i++) 106 printf("%d\n", ans[i]); 107 clear(root[1]); 108 } 109 110 return 0; 111 }
以上是关于HDU6191(01字典树启发式合并)的主要内容,如果未能解决你的问题,请参考以下文章
hdu 6191--Query on A Tree(持久化字典树)
HDU 6191Query on A Tree 可持久化字典树