01字典树(删除与添加操作)
http://acm.hdu.edu.cn/showproblem.php?pid=5536
题意:在一个数组中找出 (s[i]+s[j])^s[k] 最大的值,其中 i、j、k 各不相同。
题解:1、可直接暴力O(n3)
2、01字典树可以在数组中找到一个数与X异或和最大和其异或结果。本题中的X是数组中的两个不同的数的和,在数组中找另一个与前两个数不同的异或和最大。为了确保找到数与前两个数不同,所有要进行删除与添加操作。另开一个数组记录节点访问次数,通过对访问次数的加减进行删除与添加操作。
https://blog.csdn.net/zuzhiang/article/details/79872805
#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n ; i ++) #define INF 0x3f3f3f3f #define mod 1000000007 #define PI acos(-1) using namespace std; typedef unsigned long long ll ; int tree[32*1009][2] , vis[32*1009] , num[32*1009]; int a[1009]; int tol ; void insert(int x ) { int u = 0 ; for(int i = 31 ; i >= 0 ; i--) { int p = (x >> i)&1; if(!tree[u][p]) tree[u][p] = ++ tol ; u = tree[u][p]; num[u]++; } vis[u] = x ; } void update(int x , int add) { int u = 0 ; for(int i = 31 ; i >= 0 ; i--) { int p = (x >> i) & 1 ; u = tree[u][p]; num[u] += add; } } int research(int x) { int u = 0 ; for(int i = 31 ; i >= 0 ; i--) { int p = (x >> i) & 1 ; if(tree[u][p^1] && num[tree[u][p^1]]) u = tree[u][p^1]; else u = tree[u][p]; } return x ^ vis[u]; } void init() { memset(vis, 0 , sizeof(vis)); memset(tree , 0 , sizeof(tree)); memset(num , 0 , sizeof(num)); tol = 0 ; } int main() { int t ; scanf("%d" , &t); while(t--) { init(); int n ; scanf("%d" , &n); for(int i = 0 ; i < n ; i++) { scanf("%d" , &a[i]); insert(a[i]); } int ma = -INF ; for(int i = 0 ; i < n ; i++) { for(int j = i + 1 ; j < n ; j++) { update(a[i] , -1); update(a[j] , -1); ma = max(ma , research(a[i]+a[j])); update(a[i] , 1); update(a[j] , 1); } } cout << ma << endl ; } return 0; }
maxi,j,k(si+sj)⊕sk
maxi,j,k(si+sj)⊕sk
maxi,j,k(si+sj)⊕sk