当前位置: 首页 > news >正文

【数据结构】01Trie

什么是 01Trie?

01Trie是字典树的一种变种,其只有两种情况,即 0 和 1,实现方式其实和字典树是一样的


有什么用呢?

其一般用于解决异或问题,是一种快速的数据结构,某些情况下可以无脑套用


实现方式?

和上面说的一样,其实就是字典树,我们利用实战来讲解一下


实战运用!

P10471 最大异或对 The XOR Largest Pair - 洛谷

思路:

板子

由于要让我们选择两个数使得异或和最大,如果我们直接双重循环的话指定会爆,那我们就需要优化了,而这时就可以请出我们的01Trie了,倒不如说这就是为它而生的

对于01Trie我们必备的两个操作就是插入和查询,我们先讲解插入

我们定义 ch[][] 数组为整个01Trie的大小,由于每个数都有31位,且每位都有01两种可能,所以数组大小就是 ch[N*31][2],同时我们再定义一个 idx,其代表当前已经有了多少个节点,其中 ch[p][j]代表的是节点 p 到 j 是否存在一条边,且这条边的另一个点是谁,这样我们就能每次跳到下一个节点了,如果不存在我们就只需要把它变成新的节点即可

那么对于每次插入操作,我们都从高到低插入(之后会说为什么),然后判断是否存在这条边,如果存在那就跳到下一个节点,否则就赋予新的节点再跳

查询操作也很好写了,我们和上面插入操作类似,只不过这次我们要主动跳跃了,我们判断 x 的当前位是什么,如果是 0,那我们就判断此点与 1 是否有边,如果有那就跳,否则就跳 0,如果是 1 也是同理,那为什么要从最高位开始呢?因为如果对于 0 最高位有 1 的话,那我们跳到 1 即可,因为此后即使全是 1 也不可能比此时选 1 大,如 1000 0111

那么按照上面思路写完就结束了

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <utility>
#include <array>
#include <tuple>
using namespace std;
#define int long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endlconst int N = 100010;
int n, a[N];
int ch[N * 31][2], idx = 0;void insert(int x)
{int p = 0;for (int i = 30; i >= 0; i--){int j = x >> i & 1;if (!ch[p][j]){ch[p][j] = ++idx;}p = ch[p][j];}
}int query(int x)
{int p = 0, res = 0;for (int i = 30; i >= 0; i--){int j = x >> i & 1;if (ch[p][!j]){res += 1 << i;p = ch[p][!j];}else{p = ch[p][j];}}return res;
}void solve()
{cin >> n;for (int i = 0; i < n; i++){cin >> a[i];insert(a[i]);}int ans = 0;for (int i = 0; i < n; i++){ans = max(ans, query(a[i]));}cout << ans;
}
signed main()
{//cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

P4551 最长异或路径 - 洛谷

思路:

思维题

这题乍一看根本不知道怎么和01Trie扯上关系,但是我们要仔细分析一下

对于这棵树,我们随便以一点为根,这里以 1 为根,那么我们可以计算出每个点 x 到 1 的异或和val(1,x)是多少,一次 dfs 即可,那么知道这个有什么用呢?

对于 u v 两个点,如果我们要计算 u ~ v 的异或和,由于异或有交换律,所以我们不需要考虑顺序,那么 val(u,v) = val(1,u) ^ val(1,v),为什么呢?显然我们可以以 v 为一个中转站,然后链接 u v,如果其中有重复的路,由于 x ^ x = 0,所以重复的位置不会对答案造成影响,因此是可以这样的

所以题目就可以这样做:先 dfs 跑一边把 a[i] 求出来,然后将所有的 a[i] 加到 01Trie 中,然后跑一遍模板即可

代码:

#include <iostream>
#include <algorithm>
#include<cstring>
#include <iomanip>
#include<cctype>
#include<string>
#include <set>
#include <vector>
#include <cmath>
#include <queue>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <stack>
#include <utility>
#include <array>
#include <tuple>
using namespace std;
#define int long long
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
const int N = 100010;
int n;
int ch[N * 31][2],idx = 0;
vector<vector<pair<int, int>>> g(N);
vector<int> a(N);void insert(int x)
{int p = 0;for (int i = 30; i >= 0; i--){int j = x >> i & 1;if (!ch[p][j]){ch[p][j] = ++idx;}p = ch[p][j];}
}int query(int x)
{int p = 0,res = 0;for (int i = 30; i >= 0; i--){int j = x >> i & 1;if (ch[p][!j]){res += 1LL << i;p = ch[p][!j];}else{p = ch[p][j];}}return res;
}void dfs(int self,int fa)
{for (auto son : g[self]){if (son.first == fa){continue;}a[son.first] = a[self] ^ son.second;dfs(son.first, self);}
}void solve()
{cin >> n;for (int i = 0; i < n - 1; i++){int u, v, x;cin >> u >> v >> x;g[u].push_back({ v,x });g[v].push_back({ u,x });}dfs(1, 1);for (int i = 1; i <= n; i++){insert(a[i]);}int ans = 0;for (int i = 1; i <= n; i++){ans = max(ans, query(a[i]));}cout << ans;
}
signed main()
{//cin.tie(0)->sync_with_stdio(false);int t = 1;//cin >> t;while (t--){solve();}return 0;
}

相关文章:

  • el-table中合并表格后横向变高样式无效
  • 国标GB28181软件EasyGBS雪亮工程打造智能高效的视频监控新体系
  • MySQL锁机制详解!
  • RocketMQ的事务消息机制
  • vue 手机端 封装全局使用的提示框 (vant)
  • YOGA Air X ILL10(83CX)/YOGA 14 ILL10X(83LC)2025款恢复开箱状态原装出厂Win11系统OEM镜像
  • SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理标准)-(三)完结
  • 【LeetCode 42】接雨水(单调栈、DP、双指针)
  • 深入剖析 I/O 复用之 select 机制
  • C#简易Modbus从站仿真器
  • 2025年排名前十进销存软件大测评
  • Coding Practice,48天强训(32)
  • 【嵌入式开发-IIC】
  • OptiStruct动力分析超单元卡片说明(2)
  • 【嵌入式开发-xxxxx】
  • 计算机网络笔记(十五)——3.2点对点协议PPP
  • MySQL数据库创建、删除、修改
  • 2.4 点云数据存储格式——轻量文本型存储格式
  • 20250508在WIN10下使用移远的4G模块EC200A-CN直接上网
  • WEB UI自动化测试之Pytest框架学习
  • 中国证监会印发2025年度立法工作计划
  • 2025柯桥时尚周启幕:国际纺都越来越时尚
  • 泽连斯基称与特朗普通话讨论停火事宜
  • 中华人民共和国和俄罗斯联邦在纪念中国人民抗日战争、苏联伟大卫国战争胜利和联合国成立80周年之际关于进一步深化中俄新时代全面战略协作伙伴关系的联合声明
  • 法治日报:商品明细是隐私,外卖员快递员不应知晓
  • 国家主席习近平抵达莫斯科