01字典树例题(待学习)
01字典树用于处理数字的前缀
例题:
https://codeforces.ml/contest/1720/problem/D2
题解:
https://www.bilibili.com/video/BV1mG4y1a7QS?spm_id_from=333.1007.top_right_bar_window_view_later.content.click&vd_source=75ae018f8d1181302d7ea76b60c928f4
字典树大小开N*31,因为最多插入N(数字)*31(数位)个节点。
1是字典树的头结点。
本题中用dp[i]记录以ai为结尾的最大长度。
用val记录当前节点中全部节点的最大长度。
ch按a[i]^i的当前位进行分类;
val按i的当前位进行分类(原因题解中有讲解)。
代码:

#include<bits/stdc++.h> #define fore(x,y,z) for(LL x=(y);x<=(z);x++) #define forn(x,y,z) for(LL x=(y);x<(z);x++) #define rofe(x,y,z) for(LL x=(y);x>=(z);x--) #define rofn(x,y,z) for(LL x=(y);x>(z);x--) #define all(x) (x).begin(),(x).end() #define fi first #define se second #include<unordered_set> using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; int a[300010]; int dp[300010]; int ch[31 * 300010][2]; int val[31 * 300010][2]; int idx = 1; void insert(int x, int i) { int u = 1; for (int d = 30; d >= 0; d--) { int &v = ch[u][x >> d & 1]; if (v == 0) v = ++idx; val[v][i>>d&1]=max(val[v][i >> d & 1],dp[i]); u = v; } } int find(int x, int o) { int res = 1; int u = 1; for (int i = 30; u&&i >= 0; i--) { int v = ch[u][!(x >> i & 1)];//对当前不等的一边进行查询 res = max(res, val[v][!(o >> i & 1)]+1);//查询与o当前位不同的最大值 u= ch[u][x >> i & 1];//进入相等的一边 } return res; } void YD() { int n; cin >> n; for (int i = 0; i < n; i++) cin >> a[i]; for (int i = 0; i <= idx; i++) ch[i][0] = ch[i][1] = val[i][0] = val[i][1] = 0; idx = 1; int res = 0; for (int i = 0; i < n; i++) { dp[i] = find(a[i]^i,a[i]); res = max(res, dp[i]); insert(a[i] ^ i, i); } cout << res << endl; } int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); int t; cin >> t; while (t--) { YD(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人