题意
两个整数 x 和 y 是 兼容的,如果它们的位运算 "AND" 结果等于 0,亦即 a & b = 0 。例如,数 90 (10110102) 和 36 (1001002) 是兼容的,因为 10110102 & 1001002 = 02;而数 3 (112)和 6 (1102) 是不兼容的,因为 112 & 1102 = 102 。
给定一个整数数组 _a_1, _a_2, ..., a__n 。您的任务是判断每个数组元素:这个元素是否与给定数组中的某个其它元素兼容?如果问题的答案是肯定的,则应找出任意一个匹配的元素。
第一眼觉得用01字典树可做,但当所有值都是1的时候,每次遍历就要遍历整个字典树,很显然会T。只能考虑其他做法。
我们发现给的数据范围是400w,是可以直接用数组开下的,考虑到&运算的时候只有原数字位位1和另一个数字相同位为1的时候才会导致不匹配。
所以我们利用贪心的思想,先把能与这个数匹配的最大数直接存入数组,之后从后往前遍历,如果遇到没有匹配的数字,就考虑比他多一位1的数字有没有匹配,因为在相同位上1总为0的子集,因此这样预处理之后可直接输出,
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-9;
const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
int N,M,tmp,K;
int dp[1 << 23];
int a[maxn];
int main()
{
Sca(N);
For(i,1,N){
int x; Sca(x); a[i] = x;
dp[x ^ ((1 << 23) - 1)] = x;
}
for(int i = (1 << 23) - 1; i >= 0 ; i --){
if(!dp[i]){
for(int j = 0; j < 23; j ++){
if(dp[i | (1 << j)]){
dp[i] = dp[i | (1 << j)];
break;
}
}
}
}
For(i,1,N){
if(dp[a[i]]) printf("%d ",dp[a[i]]);
else printf("-1 ");
}
#ifdef VSCode
system("pause");
#endif
return 0;
}