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

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

第一次做可持久化字典树,感觉和主席树对线段树的更改好像啊,也是现在的状态减去过去的状态然后找答案

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+5;
ll mm;
int tree[maxn*35][2],son[maxn*35][2],rt[maxn],cnt,sta[maxn],fin[maxn];
int head[maxn],tot,now;
ll a[maxn];
struct node
{
    int to,next;
}e[maxn*2];
void add(int x,int y)
{
    e[tot].to=y;
    e[tot].next=head[x];
    head[x]=tot++;
}
void build(int last,int root,ll num,ll ret)
{
    if(ret==0)
        return ;
    ll a=ret&num;
    int v=(a==ret)?1:0;
    tree[root][v]=tree[last][v]+1;
    tree[root][v^1]=tree[last][v^1];
    son[root][v^1]=son[last][v^1];
    build(son[last][v],son[root][v]=++cnt,num,ret/2);
}
void dfs(int fa)
{
    sta[fa]=++now;
    build(rt[sta[fa]-1],rt[sta[fa]]=++cnt,a[fa],mm);
    for(int i=head[fa];~i;i=e[i].next)
    {
        int ne=e[i].to;
        dfs(ne);
    }
    fin[fa]=now;
}
ll query(int last,int root,ll num,ll sum,ll ret)
{
    if(ret==0)
        return sum;
    ll a=ret&num;
    int v=(a==ret)?0:1;
    if(tree[root][v]-tree[last][v]>0)
        return query(son[last][v],son[root][v],num,sum+ret,ret/2);
    else
        return query(son[last][v^1],son[root][v^1],num,sum,ret/2);
}
int main()
{
    int n,q;
    mm=1;
    for(int i=1;i<=31;i++)
        mm*=2;
    while(~scanf("%d%d",&n,&q))
    {
        memset(head,-1,sizeof(head));
        memset(rt,0,sizeof(rt));
        memset(tree,0,sizeof(tree));
        cnt=tot=now=0;
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]);
        int x,y;
        ll val;
        for(int i=2;i<=n;i++)
        {
            scanf("%d",&x);
            add(x,i);
        }
        dfs(1);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%lld",&x,&val);
            printf("%lld\n",query(rt[sta[x]-1],rt[fin[x]],val,0,mm));
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/82498030
今日推荐