Fellow me on GitHub

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,Fn1Fi 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 }
复制代码

 

posted @   Penn000  阅读(921)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
历史上的今天:
2016-09-16 HDU2063(二分图最大匹配)
2016-09-16 HDU4738(割边)
2016-09-16 POJ1144(割点)
2016-09-16 POJ1556(割点)
点击右上角即可分享
微信分享提示