很有技巧的一道题,题目就是给你一串n个数 (n<=105,ai<=220) 让你分别选两个数,使and or xor最大,这明明就是3道题好不好QAQ
然后我们一个一个看
以下所以“位”指的都是2进制
and:就是从最高的一位向下找,如果这一位为1的数多于两个就取出这些数,然后再取出的这些数里面继续下一位的一样的处理,我就用递归写的
or:这个比较巧妙,也比较暴力,先每个数开一个数组,然后将每个数1的子集全部变为ture,然后去查找每个数,从前向后每一位为0的看有没有可以匹配的,可以就取
xor:我觉得写起来最简单的,读的时候按每一位建一个trie tree,然后查询每一个数就取反然后在里面找,可以就加这一位,不行就不加,一直走20位就可以了
然后代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<set>
#include<queue>
#include<algorithm>
#include<vector>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<stack>
#define INF 2100000000
#define ll long long
#define clr(x) memset(x,0,sizeof(x))
#define M 100005
#define N (1<<20)
using namespace std;
int a[M];
struct tree2
{
tree2 *lson,*rson;
int n;
}*root,dizhi[M*21];
int t;
void add(int x)
{
tree2 *tree=root;
for(int i=20;i>=0;i--)
{
if(x&(1<<i))
{
if(tree->lson==NULL)tree->lson=&dizhi[++t];
tree=tree->lson;
}
else
{
if(tree->rson==NULL)tree->rson=&dizhi[++t];
tree=tree->rson;
}
}
}
int get_xor(int x)
{
tree2 *tree=root;
int ans=0;
for(int i=20;i>=0;i--)
{
if(x&(1<<i))
{
if(tree->rson!=NULL)
{
ans+=(1<<i);
tree=tree->rson;
}
else tree=tree->lson;
}
else
{
if(tree->lson!=NULL)
{
ans+=(1<<i);
tree=tree->lson;
}
else tree=tree->rson;
}
}
return ans;
}
int n,c;
int get_and(int *num,int len,int w)
{
int s[len],sta=0;
clr(s);
int b=0;
for(int i=w;i>=0;i--)
{
for(int j=1;j<=len;j++)
{
if(num[j]&(1<<i))
{
b++;
s[++sta]=num[j];
}
}
if(b>1)
{
int ret=get_and(s,sta,i-1)+(1<<i);
return ret;
}
b=0;sta=0;
}
return 0;
}
int b[N];
int get_or()
{
clr(b);
for(int i=1;i<=n;i++)b[a[i]]=1;
for(int i=0;i<=20;i++)
for(int j=0;j<=N;j++)
if(j&(1<<i))b[j^(1<<i)]|=b[j];
int mx=0;
for(int i=1;i<=n;i++)
{
int ans=a[i];
int temp=0;
for(int j=20;j>=0;j--)
if(!(a[i]&(1<<j)))
if(b[temp|(1<<j)])
{
ans|=(1<<j);
temp|=(1<<j);
}
mx=max(mx,ans);
}
return mx;
}
int main()
{
freopen("maximum.in","r",stdin);
freopen("maximum.out","w",stdout);
int T;
cin>>T;
while(T--)
{
cin>>n>>c;
if(c==2)root=&dizhi[++t];
clr(a);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(c==2)add(a[i]);
}
switch (c)
{
case 1:cout<<get_and(a,n,20)<<'\n';break;
case 2:
{
int mx=0;
for(int i=1;i<=n;i++)
mx=max(mx,get_xor(a[i]));
cout<<mx<<'\n';
break;
}
case 3:cout<<get_or()<<'\n';break;
}
}
return 0;
}
大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。