1. 程式人生 > >01字典樹(待更新)

01字典樹(待更新)

names sin %d string iostream urn stream acm 數字

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 }

下面幾道例題:

一、HDU 4825 xor sum

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

01字典樹(待更新)