Trie树上dfs跑 与 或 异或

Trie树上dfs跑与 或 异或

【题目描述】
任务是写一个位运算数据库:需要能插入整数,并快速查找数据库中的一个整数与给定的整数x按位与/按位或/按位异或能得到的最大值。

【输入格式】
第一行一个整数n,表示操作数。
接下来n行,每行两个正整数D,X。
若D=1,表示向数据库插入一个整数X。
若D=2,表示询问数据库中选择一个数与X按位与能得到的最大值。
若D=3,表示询问数据库中选择一个数与X按位或能得到的最大值。
若D=4,表示询问数据库中选择一个数与X按位异或能得到的最大值。

【输出格式】
对于每个询问操作,输出一行一个整数。

【样例数据】
aoba.in
10
1 14241
1 59992
1 48925
2 35594
1 20299
2 32836
3 40440
1 64275
4 14405
3 64859

aoba.out
35592
32832
65528
53789
65531

【数据范围】
对于30%的数据,n≤5000。
对于另30%的数据,D只会为1或4。
对于100%的数据,1≤n≤300000,0≤X<65536,保证第一个操作为插入。

思路:
贪心策略。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#define LL long long 
#define N 300010
using namespace std;

int n, ans;
int a[N]; 

struct TRIE{
    int son[2], wgh;
}trie[5000010];

int tot;
int root;

inline void Insert(const int pos, const int d, const int step){
    trie[pos].wgh++; 
    if(step < 0) return ;
    int p = (d >> step) & 1;
    if(trie[pos].son[p] == 0) trie[pos].son[p] = ++tot;
    Insert(trie[pos].son[p], d, step-1);
    return ;
}

inline int Query2(const int d, const int pos, const int step){
    if(step < 0) return 0;
    int p = (d >> step) & 1;
    if(trie[pos].son[1] == 0) trie[pos].son[1] = ++tot;
    if(trie[pos].son[0] == 0) trie[pos].son[0] = ++tot;
    if(p == 1){
        if(trie[trie[pos].son[1]].wgh)
            return (1<<step) + Query2(d, trie[pos].son[1], step-1);
        return Query2(d, trie[pos].son[0], step-1);
    }
    else{
        if(trie[trie[pos].son[1]].wgh && trie[trie[pos].son[0]].wgh)
            return max(Query2(d, trie[pos].son[0], step-1), Query2(d, trie[pos].son[1], step-1));
        else if(trie[trie[pos].son[1]].wgh)
            return Query2(d, trie[pos].son[1], step-1);
        else return Query2(d, trie[pos].son[0], step-1);
    }
}

inline int Query3(const int d, const int pos, const int step){
    if(step < 0) return 0;
    int p = (d >> step) & 1;
    if(trie[pos].son[1] == 0) trie[pos].son[1] = ++tot;
    if(trie[pos].son[0] == 0) trie[pos].son[0] = ++tot;
    if(p == 0){
        if(trie[trie[pos].son[1]].wgh)
            return (1<<step) + Query3(d, trie[pos].son[1], step-1);
        return Query3(d, trie[pos].son[0], step-1);
    }
    else{
        if(trie[trie[pos].son[1]].wgh && trie[trie[pos].son[0]].wgh)
            return (1<<step) + max(Query3(d, trie[pos].son[0], step-1), Query3(d, trie[pos].son[1], step-1));
        else if(trie[trie[pos].son[1]].wgh)
            return (1<<step) + Query3(d, trie[pos].son[1], step-1);
        else return (1<<step) + Query3(d, trie[pos].son[0], step-1);
    }
}

inline int Query4(const int d, const int pos, const int step){
    if(step < 0) return 0;
    int p = (d >> step) & 1;
    if(trie[pos].son[p^1] == 0) trie[pos].son[p^1] = ++tot;
    if(trie[trie[pos].son[p^1]].wgh)
        return (1<<step) + Query4(d, trie[pos].son[p^1], step-1);
    if(trie[pos].son[p] == 0) trie[pos].son[p] = ++tot;
    return Query4(d, trie[pos].son[p], step-1);
}

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

int main(){
    freopen ("aoba.in", "r", stdin);
    freopen ("aoba.out", "w", stdout);
    n = read();
    for(register int i=1; i<=n; ++i){
        int opt = read(), x = read();
        if(opt == 1) { Insert(root, x, 16); continue;}
        else if(opt == 2){
            ans = Query2(x, root, 16) ;
        }
        else if(opt == 3){
            ans = Query3(x, root, 16) ;
        }
        else if(opt == 4){
            ans = Query4(x, root, 16) ;//17
        }
        printf("%d\n", ans);
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/w4149/article/details/78128068
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注