01trie
01 Trie
字符集为
一般用于解决异或相关问题
基本问题
给定数集
从高到低将集合
从根节点开始,尽量选和
容易证明这一定是最大值。
时空复杂度
int tot=0; int son[N*35][2]; inline void build(LL x){ int pos=0; for(int i=33;i>=0;i--){ int bit=(x>>i)&1; if(!son[pos][bit]) son[pos][bit]=++tot; pos=son[pos][bit]; } } inline LL query(LL x){ int pos=0;LL ans=0; for(int i=33;i>=0;i--){ int bit=(x>>i)&1; if(son[pos][bit^1]) pos=son[pos][bit^1],ans+=(1ll<<i); else pos=son[pos][bit]; } return ans; }
变式 0
给定数集
很简单,每次尽量选和
变式 1-1
给定数集
对每个数都做一次基本问题就好了。
因为自己异或自己是
复杂度还是
变式 1-2
给定序列
根据异或的性质,可以推出
那么就转化成对于
注意!
扩展 1
给定数集
类似权值线段树求区间第 k 小的思路。
对 Trie 上每个点,记录子树大小(出现次数),让 k 跟和 x 不同的子树比大小,小就走和 x 不同;大就走和 x 相同,k 减去不同的子树大小。
int tot=0; int son[N*35][2],siz[N*35]; inline void build(LL x){ int pos=0; for(int i=33;i>=0;i--){ int bit=(x>>i)&1;siz[pos]++; if(!son[pos][bit]) son[pos][bit]=++tot; pos=son[pos][bit]; } siz[pos]++; } inline LL query(LL x,LL rk){ int pos=0;LL ans=0; for(int i=33;i>=0;i--){ int bit=(x>>i)&1; if(!son[pos][bit^1]) pos=son[pos][bit]; else if(rk<=siz[son[pos][bit^1]]) pos=son[pos][bit^1],ans|=1ll<<i; else rk-=siz[son[pos][bit^1]],pos=son[pos][bit]; } return ans; }
扩展 1-1
给定数集
优先队列维护对每个数来说,异或和第 t 大(初始 t 为 1)
每次取出堆顶,将第 t+1 大加入队列。
可以保证第 i 次取到的数是第 i 大。
由于每个异或和会统计两次(两数交换),所以第 2k 次取到的就是答案。
扩展 2
给定一棵带权树,求树上最大异或路径。
(某些人可能就想写树剖了,但你别急
记
由于根节点到
问题转化成给定数集求两两最大异或和。
01 Trie 是个挺神奇的东西qwq
如果有错误或者不清楚的地方欢迎评论/私信
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效