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>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 
#define LLONG_MAX 9223372036854775807

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 1e9+7;
const int maxn = 2e6+11;
const int maxm = 1e5+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);

int tot;
int n, q;
int a[maxm];
int root[maxm];
int trie[maxn][2];
vector<int>v[maxm];
queue<int>pool;
int build(){
    if(!pool.empty()){
        int x = pool.front();
        pool.pop();
        return x;
    }
    ++tot;
    return tot;
}
void insert(int root, int t){
    for(int i = 31; i >= 0; i--){
        int x = (t>>i)&1;
        if(!trie[root][x])trie[root][x]=build();
        root = trie[root][x];
    }
    return;
}
int query(int root, int t){
    int ans = 0;
    for(int i = 31; i >= 0; i--){
        int x = (t>>i)&1;
        if(trie[root][x^1]){
            ans|=(1<<i);
            root = trie[root][x^1];
        }
        else root = trie[root][x];
    }
    return ans;
}
vector<PI>ask[maxn];
void del(int x){
    if(!x)return;
    pool.push(x);
    return;
}
int merge(int p, int q){
    if(!p)return q;
    if(!q)return p;
    trie[p][0] = merge(trie[p][0], trie[q][0]);
    trie[p][1] = merge(trie[p][1], trie[q][1]);
    trie[q][0]=trie[q][1]=0;
    del(q);
    return p;
}
int ans[maxn];
void dfs(int x){
    root[x] = build();
    insert(root[x], a[x]);
    for(int i = 0; i < (int)v[x].size(); i++){
        int y = v[x][i];
        dfs(y);
        root[x] = merge(root[x],root[y]);
    }
    for(int i = 0; i < (int)ask[x].size(); i++){
        ans[ask[x][i].fst] = query(root[x], ask[x][i].sc);
    }
    return;
}

int main(){
    while(~scanf("%d %d", &n, &q)){  
        tot = 0;
        while(!pool.empty())pool.pop();
        mem(trie,0);
        for(int i = 1; i <= n; i++){
            v[i].clear();
            ask[i].clear();
            root[i]= 0;
            scanf("%d", &a[i]);
        }
        for(int i = 2; i <= n; i++){
            int x;
            scanf("%d", &x);
            v[x].pb(i);
        }
        for(int i = 1; i <= q; i++){
            int u, x;
            scanf("%d %d", &u, &x);
            ask[u].pb(make_pair(i,x));
        }
        dfs(1);
        for(int i = 1; i <= q; i++){
            printf("%d\n",ans[i]);
        }
        del(root[1]);
    }
    return 0;
}
/*
2 2
1 2
1
1 3
2 1

3 2
1 2 3
1 1
3 4
1 3

11 4
1 2 3 4 5 6 7 8 9 10 11
1 1 1 2 2 3 4 4 4 5
2 5
3 6
1 2
8 7

100000 2
1 55
2 33
 */

 

posted @ 2019-05-04 00:59  wrjlinkkkkkk  阅读(184)  评论(0编辑  收藏  举报