您的位置:首页 > 其它

01字典树的应用

2019-07-29 16:30 56 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_40534166/article/details/97646997

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: