01字典树的应用

01字典树的应用

01Trie可以快速处理一堆数字
既然trie树比较与字符串亲近,我们就想方设法地把数字转成字符串
没错!就是二进制!

在这里插入图片描述

01Trie的应用(1):
给出一个集合,多次询问,每次给出一个数,求这个数和集合中的数的异或的最大值。

根据位运算的性质,高位越大越好。 按照数字的二进制建立 Trie,对于一个询问,从上往下走,贪心的选异或起来更大的方向走,直到走到叶子。

具体实现:

#include<bits/stdc++.h>
#define Rep(a,b,c) for(register int a=b;a<=c;a++)
#define Mem(d,e) memset(d,e,sizeof(d))
using namespace std;
int bits[25],a[300007],cnt=0,opt=0;
 
inline int in(){
    
    
	int W=1,X=0;
	char Ch=0;
	while(!isdigit(Ch)){
    
    
		if(Ch=='-') W=-1;
		Ch=getchar();
	}
	while(isdigit(Ch))
		X=(X<<3)+(X<<1)+(Ch^'0'),Ch=getchar();
	return X*W;
}
 
inline void out(int M,char *s){
    
    
	if(M<0) putchar('-'),M=-M;
	if(M>9) out(M/10,"");
	putchar(M%10+'0');
	printf(s);
	return;
}
 
inline void getbits(){
    
    
	bits[0]=1;
	Rep(i,1,19)
		bits[i]=bits[i-1]<<1;
	return;
}
 
struct Node{
    
    
	int son[2],id;
};
 
struct Trie{
    
    
	Node s[1<<24];
	inline void build(){
    
    
		Mem(s,0),getbits();
	}
	inline void add(int cur,int dep,int x){
    
    
		if(dep<0) {
    
    
			s[cur].id=x;
			return;
		}
		bool tmp=bits[dep]&x;
		add(s[cur].son[tmp]=++cnt,dep-1,x);
	}
	inline int query(int cur,int dep){
    
    
		if(dep<0) return s[cur].id;
		bool tmp=bits[dep]&opt;
		if(s[cur].son[tmp^1]);
			return query(s[cur].son[tmp^1],dep-1);
		return query(s[cur].son[tmp],dep-1);
	}
}A;
 
 
int main(){
    
    
	int n,q;
	n=in(),q=in();
	A.build();
	Rep(i,1,n)
		a[i]=in();
	sort(a+1,a+n+1);
	n=unique(a+1,a+n+1)-a-1;
	while(n)
		A.add(0,19,a[n--]);
	while(q--){
    
    
		opt=in();
		out(A.query(0,19),"\n");
	}
}

应用2——特殊的01Trie
CF842D

题意简述:
维护一个长度为n的序列,每次给出一个x ,请进行如下操作:
1.把序列中的所有数和 x异或
2.查询这个序列的 mex(最小的没有出现过的非负整数)
题目可以等价为:
给出一个集合,多次查询,每次查询给出一个x,问集合中所有数异或上x之后的 mex
建出 0/1 Trie,从上往下走。如果左儿子满了,就递归到右儿子,否则递归到左儿子,直到叶子即为答案。

#include <cstdio>
#include <algorithm>
using namespace std;

int trie[6000005][2], tot = 1, has[6000005];

void insert(int n)
{
    
    
    int t = 1;
    for(int i = 20; i > 0; i--)
    {
    
    
        has[t]++;
        if(n & (1 << (i - 1)))
        {
    
    
            if(!trie[t][1]) trie[t][1] = ++tot;
            t = trie[t][1];
        } else {
    
    
            if(!trie[t][0]) trie[t][0] = ++tot;
            t = trie[t][0];
        }
    }
    has[t]++;
}

int dlt = 0;

int query()
{
    
    
    int t = 1, res = 0;
    for(int i = 20; i > 0; i--)
    {
    
    
        if(dlt & (1 << (i - 1)))
        {
    
    
            if(!trie[t][1])
            {
    
    
                return res;
            } else if(has[trie[t][1]] < (1 << (i - 1))) {
    
    
                t = trie[t][1];
            }
            else
            {
    
    
                t = trie[t][0];
                res += (1 << (i - 1));
            }
        }
        else
        {
    
    
            if(!trie[t][0])
            {
    
    
                return res;
            }
            else if(has[trie[t][0]] < (1 << (i - 1)))
            {
    
    
                t = trie[t][0];
            }
            else
            {
    
    
                t = trie[t][1];
                res += (1 << (i - 1));
            }
        }
    }
    return res;
}

int n, m, a[300005], t;

int main()
{
    
    
    scanf("%d%d", &n, &m);
    for(int i = 0; i < n; i++)
    {
    
    
        scanf("%d", &a[i]);
    }
    sort(a, a + n);
    n = unique(a, a + n) - a;
    for(int i = 0; i < n; i++)
    {
    
    
        insert(a[i]);
    }
    for(int i = 0; i < m; i++)
    {
    
    
        scanf("%d", &t);
        dlt ^= t;
        printf("%d\n", query());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40534166/article/details/97646997