[hdu 6191] Query on A Tree

Query on A Tree

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 733    Accepted Submission(s): 275

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−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

2017ACM/ICPC广西邀请赛-重现赛(感谢广西大学)

显然,又是data structure。。。

网上有用DFS序来做的,但是本蒟蒻并不太清楚他们dalao的做法,所以只是大了一发可持久化trie合并。。

对于这一题,主要涉及trie的合并,要将u的子节点的信息合并到u的身上去。

那么,假设要将v的信息并到u上,则:

1 int merge(int u,int v) {
2     if (!u) return v;
3     if (!v) return u;
4     ch[u][0]=merge(ch[u][0],ch[v][0]);
5     ch[u][1]=merge(ch[u][1],ch[v][1]);
6     return u;
7 }

那么这题差不多就可以A了。

code:

 1 %:pragma gcc optimize(3)
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #define jug(i,x) (((1<<i)&x)>0)
 7 #define M(a,x) memset(a,x,sizeof a)
 8 using namespace std;
 9 const int N=100005,Nod=12000005;
10 int n,tot,Q,a[N],lnk[N],nxt[N],son[N];
11 int ro[N],ans[N];
12 struct que {int v,i;};
13 vector <que> qr[N];
14 struct persistent_trie {
15     int cnt,ch[Nod][2];
16     void init() {cnt=1;}
17     int newnode() {
18         M(ch[cnt],0);
19         return cnt++;
20     }
21     int merge(int x,int y) {
22         if (!x) return y;
23         if (!y) return x;
24         ch[x][0]=merge(ch[x][0],ch[y][0]);
25         ch[x][1]=merge(ch[x][1],ch[y][1]);
26         return x;
27     }
28     void insert(int x,int v) {
29         int u=ro[x];
30         for (int i=30; i>=0; i--) {
31             bool c=jug(i,v);
32             if (!ch[u][c]) ch[u][c]=newnode();
33             u=ch[u][c];
34         }
35     }
36     int query(int x,int v) {
37         int u=ro[x],ret=0;
38         for (int i=30; i>=0; i--) {
39             bool c=jug(i,v);
40             if (ch[u][1-c]) ret|=(1<<i),u=ch[u][1-c];
41             else u=ch[u][c];
42         }
43         return ret;
44     }
45 }pt;
46 inline int read() {
47     int x=0; char ch=getchar();
48     while (ch<‘0‘||ch>‘9‘) ch=getchar();
49     while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();
50     return x;
51 }
52 void add(int x,int y) {
53     nxt[++tot]=lnk[x],son[tot]=y,lnk[x]=tot;
54 }
55 void DFS(int x) {
56     ro[x]=pt.newnode();
57     pt.insert(x,a[x]);
58     for (int j=lnk[x]; j; j=nxt[j])
59         DFS(son[j]),ro[x]=pt.merge(ro[x],ro[son[j]]);
60     for (int i=0,si=qr[x].size(); i<si; i++)
61         ans[qr[x][i].i]=pt.query(x,qr[x][i].v);
62 }
63 int main() {
64     while (scanf("%d%d",&n,&Q)!=EOF) {
65         tot=0,M(lnk,0),M(nxt,0),M(ans,0),pt.init();
66         for (int i=1; i<=n; i++) a[i]=read();
67         for (int i=1; i<n; i++) {
68             int x=read(); add(x,i+1);
69         }
70         for (int i=1; i<=n; i++) qr[i].clear();
71         for (int i=1; i<=Q; i++) {
72             int x=read(); que now;
73             now.i=i,now.v=read(),qr[x].push_back(now);
74         }
75         DFS(1);
76         for (int i=1; i<=Q; i++) printf("%d\n",ans[i]);
77     }
78     return 0;
79 }

时间: 2024-10-12 17:11:31

[hdu 6191] Query on A Tree的相关文章

hdu 6191 Query on A Tree(dfs序+可持久化字典树)

题目链接:hdu 6191 Query on A Tree 题意: 给你一棵树,每个节点有一个值,现在有q个询问,每个询问 询问一个u x,问以u为根的子树中,找一个节点,使得这个节点的值与x异或的值最大,输出那个最大的值. 题解: dfs序和一棵可持久化字典树就搞定了. 1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=a;i<=b;++i) 4

HDU 3804 Query on a tree (树链剖分)

题目链接~~> 做题感悟:这题开始想错的方法,开始想用二分来着,但是写出来之后发现不对,悲剧.. 解题思路: 看到这种只有询问没有修改的就有点离线的感脚.果不其然,就是用离线,因为要查询路径上不大于 Wi 的最大权值 ,so 我们可以以 Wi 为标准往线段树中插入数据,然后就是问线,跟求逆序数差不多.这样就不会影响最终结果,处理完后排个序就ok 了. 代码: #pragma comment(linker, "/STACK:1024000000,1024000000") #incl

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

lca的做法还是很明显的,简单粗暴, 不过不是正解,如果树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的,估计就是放在splay上剖分一下,做法还是比较复杂的,,, 来一发lca: #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #inc

hdu 4912 Paths on the tree(树链剖分+贪心)

题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道,要求尽量选出多的通道,并且两两通道不想交. 解题思路:用树链剖分求LCA,然后根据通道两端节点的LCA深度排序,从深度最大优先选,判断两个节点均没被标 记即为可选通道.每次选完通道,将该通道LCA以下点全部标记. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include

HDU 4912 Paths on the tree

http://acm.hdu.edu.cn/showproblem.php?pid=4912 题意:给一棵树,再给一些路径,求最多有多少条路径不相交. 题解:主要是贪心的想法.用LCA处理出路径的层数,然后从最深处的节点往上找.因为节点越深,对其他路径影响度越小,相交的可能性越低.需要手动扩栈. 1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include <iostream> 3 #include

hdu 4912 Paths on the tree(树链拆分+贪婪)

题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LCA深度排序,从深度最大优先选.推断两个节点均没被标 记即为可选通道. 每次选完通道.将该通道LCA下面点所有标记. #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #includ

spoj 375 Query on a tree (树链剖分)

Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. We will ask you to perfrom some instructions of the following form: CHANGE i ti : change the cost of the i-th edge to ti or Q

hdu 4863 Centroid of a Tree 树dp

代码来自baka.. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<set> #include<cmath> #include<vecto

HDU 1325 Is It A Tree? (POJ 1308)

并查集问题... 这题以前做过-- 以前做过-- 做过-- 过-- 不过重做时候被吭得异常之爽-- 在判断 vis[i]的时候.我记得标准C++是非0 即为真. 而我用C++ 提交的时候 if(vis[i]) 去直接给我WA了. 用G++ 就AC了...然后改成if(vis[i]==1) 交C++ 就AC了. 特瞄的我每次初始化都把 vis[i] 都赋值为 0 了..都能出这种错? 求路过大神明示我的错误. 题意是判断是否是一棵树. 不能存在森林,用并查集合并,每个点的入度不能超过1. 比如 1