01字典树典型的题就是找出异或值最大的两个数,其实跟字典树差不多的,就是从原来的26位字母变成了0和1,插入操作也跟字典树差不多,查询的时候有贪心思想,尽量找同位不相同的。
模板:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 7 const int N=1e5+5; 8 9 struct node{ 10 int next[2]; 11 int val; 12 void reset(){ 13 next[0]=next[1]=val=0; 14 } 15 }T[N*32];//数组大小为数字个数*最大位数 16 17 int cnt;//字典树上的节点个数 18 19 void init(){ 20 cnt=0; 21 T[0].reset(); 22 } 23 24 //将x插入到01字典树上 25 void insert(int x){ 26 int cur=0;//从根节点开始 27 for(int i=31;i>=0;i--){ 28 int t=(x>>i)&1; 29 if(!T[cur].next[t]){ 30 //将下一个新节点初始化 31 T[++cnt].reset(); 32 T[cur].next[t]=cnt; 33 } 34 cur=T[cur].next[t]; 35 } 36 //插入x 37 T[cur].val=x; 38 } 39 40 //查询在字典树中查找和x异或的值最大的元素 41 int query(int x){ 42 int cur=0; 43 for(int i=31;i>=0;i--){ 44 int t=(x>>i)&1; 45 //贪心,尽量找不同的使异或值最大 46 if(T[cur].next[t^1]) 47 cur=T[cur].next[t^1]; 48 else 49 cur=T[cur].next[t]; 50 } 51 return T[cur].val; 52 }
下面几道例题:
给你n个数,m次查询,输出n个数中与查询地数x异或值最大的数,模板题
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e5+5; struct node{ int next[2]; int val; void reset(){ next[0]=next[1]=val=0; } }T[N*32];//数组大小为数字个数*最大位数 int cnt;//字典树上的节点个数 void init(){ cnt=0; T[0].reset(); } //将x插入到01字典树上 void insert(int x){ int cur=0;//从根节点开始 for(int i=31;i>=0;i--){ int t=(x>>i)&1; if(!T[cur].next[t]){ //将下一个新节点初始化 T[++cnt].reset(); T[cur].next[t]=cnt; } cur=T[cur].next[t]; } //插入x T[cur].val=x; } //查询在字典树中查找和x异或的值最大的元素 int query(int x){ int cur=0; for(int i=31;i>=0;i--){ int t=(x>>i)&1; //贪心,尽量找不同的使异或值最大 if(T[cur].next[t^1]) cur=T[cur].next[t^1]; else cur=T[cur].next[t]; } return T[cur].val; } int main(){ int t,cas=0; scanf("%d",&t); while(t--){ init(); int n,m,x; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&x); insert(x); } printf("Case #%d:\n",++cas); for(int i=1;i<=m;i++){ scanf("%d",&x); printf("%d\n",query(x)); } } return 0; }
原文地址:https://www.cnblogs.com/fu3638/p/8136775.html
时间: 2024-10-03 20:06:40