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