社区讨论

一个线性空间复杂度的01Trie

学术版参与者 4已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@mhjto54g
此快照首次捕获于
2025/11/04 08:20
4 个月前
此快照最后确认于
2025/11/04 08:20
4 个月前
查看原帖
知乎上刷到有人推荐使用 01Trie 代替平衡树,常数很低并且也好写。
我想了一下能否替代树套树中的平衡树,但是原版 01Trie 的空间复杂度是 O(NlogN)O(N \log N) 的 (NN 为数字的个数),再套一个线段树直接变成 O(Nlog2N)O(N\log^2 N)
但再想一下似乎可以压缩公共节点,那么似乎可以做到 O(N)O(N) 的空间复杂度了,而且时间常数也随之有所下降。
题目是 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 条回复,欢迎继续交流。

正在加载回复...