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?
 

 

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?1Fi 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.

2n,q105

0Vi109

1Fin, the root of the tree is node 1.

1un,0x109
 

 

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 6191--Query on A Tree(持久化字典树)

HDU 6191Query on A Tree 可持久化字典树

HDU - 4358 Boring counting (树上启发式合并/线段树合并)

启发式合并

HDU 6191 Query on A Tree