1. 程式人生 > >2017廣西邀請賽 Query on A Tree (可持續化字典樹)

2017廣西邀請賽 Query on A Tree (可持續化字典樹)

題意 second for each follow n) nod pair content back

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;
}

2017廣西邀請賽 Query on A Tree (可持續化字典樹)