社区讨论
一个线性空间复杂度的01Trie
学术版参与者 4已保存回复 4
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 4 条
- 当前快照
- 1 份
- 快照标识符
- @mhjto54g
- 此快照首次捕获于
- 2025/11/04 08:20 4 个月前
- 此快照最后确认于
- 2025/11/04 08:20 4 个月前
知乎上刷到有人推荐使用 01Trie 代替平衡树,常数很低并且也好写。
我想了一下能否替代树套树中的平衡树,但是原版 01Trie 的空间复杂度是 的 ( 为数字的个数),再套一个线段树直接变成 。
但再想一下似乎可以压缩公共节点,那么似乎可以做到 的空间复杂度了,而且时间常数也随之有所下降。
题目是 P10471
CPP#include <bits/stdc++.h>
using namespace std;
#define int long long
#define L(i, l, r) for (int i = (l); i <= (r); i++)
#define R(i, r, l) for (int i = (r); i >= (l); i--)
#define wr(...) printf(__VA_ARGS__)
using sint = signed;
int rd() {
int ret = 0;
bool sgn = 0;
char c = getchar();
while (c < '0' || c > '9') {
sgn |= (c == '-');
c = getchar();
}
while (c >= '0' && c <= '9') {
ret = ret * 10 + c - '0';
c = getchar();
}
return sgn ? -ret : ret;
}
constexpr int N = 1e5+7;
constexpr int inf = 0x3f3f3f3f3f3f3f3f;
namespace trie {
constexpr int B=31;
struct T {
int v,h;
sint ch[2];
};
T t[2*N];
int ts;
void init() {
ts=0;
}
sint load(int v,int h) {
assert(ts+1<2*N);
t[++ts]= {v,h,{0,0}};
return ts;
}
sint root() {
return load(0,B);
}
int dif(int h,int x,int y) {
R(i,h,0) {
bool a=(x>>i)&1,b=(y>>i)&1;
if(a!=b) {
return i;
}
}
return -1;
}
void insert(sint o,int x) {
while(t[o].h>0) {
bool b=(x>>(t[o].h-1))&1;
int c=t[o].ch[b];
if(c) {
int d=dif(t[o].h,t[c].v,x);
if(d>=t[c].h) {
int a;
t[o].ch[b]=a=load((x>>(d+1))<<(d+1),d+1);
bool db=(x>>d)&1;
t[a].ch[db]=load(x,0);
t[a].ch[db^1]=c;
o=t[a].ch[db];
} else {
o=c;
}
} else {
t[o].ch[b]=load(x,0);
}
}
}
int query(sint o,int x) {
while(t[o].h>0) {
bool b=(x>>(t[o].h-1))&1;
int c=t[o].ch[b^1];
if(c) {
o=c;
} else {
o=t[o].ch[b];
}
}
return t[o].v;
}
}
int n;
int a[N];
void task() {
n=rd();
int root=trie::root();
L(i,1,n) {
a[i]=rd();
trie::insert(root,a[i]);
}
int ans=0;
L(i,1,n) {
int b=trie::query(root,a[i]);
ans=max(ans,a[i]^b);
}
wr("%lld\n",ans);
}
sint main() {
int T = 1;
while (T--) {
task();
}
return 0;
}
回复
共 4 条回复,欢迎继续交流。
正在加载回复...