2017广西邀请赛 Query on A Tree (可持续化字典树)

Query on A Tree

时间限制: 8 Sec  内存限制: 512 MB
提交: 15  解决: 3
[提交][状态][讨论版]

题目描述

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?

输入

There are no more than six test cases.
For each test case there are two positive integers n(2 ≤ n ≤ 105) and q(2 ≤ q ≤ 105), indicating 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(0 ≤ Vi ≤ 109), indicating the value of node i. The root of the tree is node 1.
The second line contains n-1 non-negative integers F1, F2,...Fn−1, Fi(1 ≤ Fi ≤ n) means the father of node i + 1.
And then q lines follow.
In the i-th line, there are two integers u(1 ≤ u ≤ n) and x(0 ≤ x ≤ 109), indicating that the node you pick should be in the subtree of u, and x has been described in the problem.

输出

样例输入

2 2
1 2
1
1 3
2 1

样例输出

2
3【题意】给你一棵树,每个节点有权值,Q次询问,求u为跟的子树里与x亦或后的值最大是多少。【分析】可持续化字典树可用来解决一段区间内与x亦或后的值最大是多少,这里可以用dfs序将子树转为序列。
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
#define mp make_pair
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 2e5+5;;
const int M = 17;
const int mod = 1e9+7;
const int mo=123;
const double pi= acos(-1.0);
typedef pair<int,int>pii;

int bin[31];
int n,m,tot;
int a[N],root[N],id[N],st[N],ed[N];
vector<int>edg[N];
struct trie{
    int cnt;
    int ch[N*32][2],sum[N*32];
    void init(){
        met(ch,0);met(sum,0);
        cnt=0;
    }
    int insert(int x,int val){
        int tmp,y;tmp=y=++cnt;
        for(int i=30;i>=0;i--)
        {
            ch[y][0]=ch[x][0];ch[y][1]=ch[x][1];
            sum[y]=sum[x]+1;
            int t=val&bin[i];t>>=i;
            x=ch[x][t];
            ch[y][t]=++cnt;
            y=ch[y][t];
        }
        sum[y]=sum[x]+1;
        return tmp;
    }
    int query(int l,int r,int val){
        int tmp=0;
        for(int i=30;i>=0;i--)
        {
            int t=val&bin[i];t>>=i;
            if(sum[ch[r][t^1]]-sum[ch[l][t^1]])
                tmp+=bin[i],r=ch[r][t^1],l=ch[l][t^1];
            else r=ch[r][t],l=ch[l][t];
        }
        return tmp;
    }
}trie;
void dfs(int u,int fa){
    st[u]=++tot;
    id[tot]=u;
    for(int i=0;i<edg[u].size();i++){
        int v=edg[u][i];
        if(v==fa)continue;
        dfs(v,u);
    }
    ed[u]=tot;
}
int main(){
    bin[0]=1;for(int i=1;i<=30;i++)bin[i]=bin[i-1]<<1;
    while(~scanf("%d%d",&n,&m)){
        root[0]=0;tot=0;
        trie.init();
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),edg[i].clear();
        for(int i=2;i<=n;i++){
            int v;
            scanf("%d",&v);
            edg[v].pb(i);
        }
        dfs(1,0);
        for(int i=1;i<=n;i++)root[i]=trie.insert(root[i-1],a[id[i]]);
        int l,r,x,u;
        while(m--){
            scanf("%d%d",&u,&x);
            l=st[u];r=ed[u];
            printf("%d\n",trie.query(root[l-1],root[r],x));
        }
    }
    return 0;
}
时间: 2024-08-23 23:07:58

2017广西邀请赛 Query on A Tree (可持续化字典树)的相关文章

Tree(可持续化字典树)

题意:询问树上结点x到结点y路上上的权值异或z的最大值. 任意结点权值 ≤ 2^16,可以想到用字典树. 但是因为是询问某条路径上的字典树,将字典树可持续化,字典树上的结点保存在这条路径上的二进制数. 按照dfs序建树,结点u的字典树表示u到根结点路径上的字典树. 如果两个结点u和v,在同一条通往根结点的路径上,将会满足可减性. 因此只需要知道u.v.lca和fa[lca]四个结点的字典树就可以回答了. /*********************************************

HDU6191 Query on A Tree (01字典树+启发式合并)

题意: 给你一棵1e5的有根树,每个节点有点权,1e5个询问(u,x),问你子树u中与x异或最大的值是多少 思路: 自下而上启发式合并01字典树,注意合并时清空trie 线段树.字典树这种结构确定的数据结构,启发式合并的时候不需要考虑次序,复杂度都是nlogn 代码: 2200 / 10000ms , 60 / 128 M #include<iostream> #include<cstdio> #include<algorithm> #include<cmath&

BZOJ_1803_Spoj1487 Query on a tree III_主席树+dfs序

BZOJ_1803_Spoj1487 Query on a tree III_主席树 Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. I

【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

[BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node whose label is k-th largest in the subtree of the node x. Assume no two nodes have the same labels. Input

HDU6186 2017广西邀请赛 CS Course (前缀和后缀)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6186 思路:题目要求的删除第q个数候所有数的 & | ^和,所以提前求出前缀和后缀,每次& | ^ 前i-1个和后i+1个即可.注意a^b^b=a; #include <iostream> #include <cstdio> using namespace std; const long long maxn=1e5+10; int n,q; long long f1[m

bzoj 1803: Spoj1487 Query on a tree III(主席树)

题意 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点) 假设没有两个相同的点权. 输入格式: 第一行为整数n,第二行为点权,接下来n-1行为树边,接下来一行为整数m,下面m行为两个整数x,k,代表query(x,k) 输出格式: m行,输出每次查询的结果. 题解 先一遍dfs,然后建个主席树,带上去直接跑一跑就好了 我忘了注意dfs序的位置和原来的编号……结果调了半天啥都调不出来…… 1 //minamot

trie tree(字典树)

hihocoder题目(http://hihocoder.com/problemset):#1014 trie树 1 #include <iostream> 2 using namespace std; 3 class trieTree 4 { 5 public: 6 trieTree() 7 { 8 isword=false; 9 for (int i=0;i<26;i++) 10 { 11 next[i]=NULL; 12 } 13 } 14 ~trieTree() 15 { 16

[LeetCode] Implement Trie (Prefix Tree) 实现字典树(前缀树)

Implement a trie with insert, search, and startsWith methods. Note:You may assume that all inputs are consist of lowercase letters a-z. http://dongxicheng.org/structure/trietree/

2017 ICPC 广西邀请赛1004 Covering

Covering Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 187    Accepted Submission(s): 107 Problem Description Bob's school has a big playground, boys and girls always play games here after sch