HDU 4825 字典树

xiaoxiao2021-02-28  144

题意

中文题,不解释

题解

很普通的字典树,不过使用上还是有一些技巧的。首先的话,倒着对位存储数组进行赋值。然后存储到字典树以及查询的时候,正着查询,查询的时候尽量向相反的方向查询。这样的话,便可以得到异或值最大的数。

注意事项

两个需要注意的地方。 第一个地方是存储数位需要倒着存储,这样的话可以保证取得的结果异或值最大。越高位异或值为1越好。 第二个地方是字典树初始化问题,需要注意根节点下标为0,子节点下标就要从1开始。

代码

#include <iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<cmath> #include<queue> #include<string> #include<set> #include<map> #include<bitset> #include<stack> #define UP(i,l,h) for(int i=l;i<h;i++) #define DOWN(i,h,l) for(int i=h-1;i>=l;i--) #define W(a) while(a) #define MEM(a,b) memset(a,b,sizeof(a)) #define INF 0x3f3f3f3f3f3f3f3f #define LL long long #define MAXN 4000010 #define EPS 1e-10 #define MOD 1000000007 using namespace std; int tree[MAXN][2]; int val[MAXN*2]; int dig[50]; int sz; void insert(int x){ int u=0; UP(i,0,35){ int v=dig[i]; if(!tree[u][v]){ val[sz]=0; tree[u][v]=sz++; } u=tree[u][v]; } val[u]=x; } int query(int x){ int u=0; UP(i,0,35){ int v=1-dig[i]; if(tree[u][v]){ u=tree[u][v]; }else{ u=tree[u][v^1]; } } // cout<<u<<"u"<<endl; return val[u]; } int bin(int x){ MEM(dig,0); DOWN(i,35,0){ if(x){ dig[i]=x%2; x/=2; }else{ dig[i]=0; } } } int main(){ int t; scanf("%d",&t); int ks=0; W(t--){ printf("Case #%d:\n",++ks); sz=1; MEM(tree,0); MEM(val,0); int n,m; scanf("%d%d",&n,&m); W(n--){ int x; scanf("%d",&x); bin(x); insert(x); } W(m--){ int x; scanf("%d",&x); bin(x); printf("%d\n",query(x)); } } }
转载请注明原文地址: https://www.6miu.com/read-36676.html

最新回复(0)