题意:
给出一个数组\(s\),求
\[
max_{i,j,k}(s_i + s_j)\oplus s_k ,i\neq j\neq k
\]
思路:
01字典树,首先还是正常插入。可以想到枚举\(i\)、\(j\)的和,再字典树跑\(k\),这里涉及下标不能相同,所以可以把\(i\)、\(j\),先删除了。在插入的时候计数\(cnt[u]++\),删除就依次把到达的各点\(cnt[u]--\)。跑\(k\)的时候判断是否可到达即可。
#include<bits/stdc++.h> using namespace std; const int N = 100010; const int inf = 0X3f3f3f3f; const long long INF = 0x3f3f3f3f3f3f3f3f; const double eps = 1e-6; const double pi = acos(-1.0); const int mod = 1000000007; typedef long long ll; int _; int n; int a[1010]; int tri[32 * 1010][2]; int cnt[32 * 1010], val[32 * 1010]; int tot; void init() { memset(tri, 0, sizeof(tri)); memset(val, 0, sizeof(val)); memset(cnt, 0, sizeof(cnt)); tot = 1; } void Insert(int x) { int u = 0; for (int i = 31; i >= 0; i--) { int bit = (x & (1 << i)) ? 1 : 0; if (!tri[u][bit]) tri[u][bit] = tot++; u = tri[u][bit]; cnt[u]++; } val[u] = x; } void Del(int x) { int u = 0; for (int i = 31; i >= 0; i--) { int bit = (x & (1 << i)) ? 1 : 0; u = tri[u][bit]; cnt[u]--; } } int Query(int x) { int u = 0; for (int i = 31; i >= 0; i--) { int bit = (x & (1 << i)) ? 1 : 0; if (tri[u][bit ^ 1] && cnt[tri[u][bit ^ 1]] > 0) { u = tri[u][bit ^ 1]; } else { u = tri[u][bit]; } } return x ^ val[u]; } int main() { for (scanf("%d", &_); _; _--) { init(); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); Insert(a[i]); } int ans = 0; for (int i = 1; i <= n; i++) { Del(a[i]); for (int j = i + 1; j <= n; j++) { Del(a[j]); ans = max(ans, Query(a[i] + a[j])); Insert(a[j]); } Insert(a[i]); } printf("%d\n", ans); } }
来源:https://www.cnblogs.com/ACMerszl/p/12222723.html