标签:ini ret acm out math style sizeof 另一个 for
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是数组中的两个不同的数的和,在数组中找另一个与前两个数不同的异或和最大。为了确保找到数与前两个数不同,所有要进行删除与添加操作。另开一个数组记录节点访问次数,通过对访问次数的加减进行删除与添加操作。
#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;
}
标签:ini ret acm out math style sizeof 另一个 for
原文地址:https://www.cnblogs.com/nonames/p/12222504.html