题目描述
给定一个含有
n
个正整数的序列
其中
op
可能是与、或和异或。
本题数据
T
组数据。
题目分析
考虑枚举每一个
Ai
,然后二进制从高位到低位贪心得到最优解。
如果运算符是异或,显然我们可以在字典树上查找。
如果运算符是与或者或,我们在贪心的过程中相当于限制了二进制某些位置一定为
1
(既要满足当前的也要满足以前的约束)。我们现在要解决的问题是如何求出
令
总的时间复杂度
O(nlog2A+Alog2A)
。
代码实现
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cctype>
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int N=100500;
const int D=20;
const int V=1<<D;
int n,c,T,ans;
int num[N];
inline int opt(int x,int y){return c==1?x&y:(c==2?x^y:x|y);}
namespace XOR
{
const int S=N*(D+1);
struct trie
{
int next[S][2],size[S];
int tot,root;
int newnode()
{
size[++tot]=0,next[tot][0]=next[tot][1]=0;
return tot;
}
void init(){tot=0,root=newnode();}
void insert(int x)
{
int rt=root;
size[rt]++;
for (int d=D-1;d>=0;d--)
{
if (!next[rt][(x>>d)&1]) next[rt][(x>>d)&1]=newnode();
size[rt=next[rt][(x>>d)&1]]++;
}
}
int maxxor(int x)
{
int rt=root,ret=0;
for (int d=D-1;d>=0;d--) rt=next[rt][((x>>d)&1)^1]?ret+=1<<d,next[rt][((x>>d)&1)^1]:next[rt][(x>>d)&1];
return ret;
}
}t;
void calc()
{
ans=-1,t.init();
for (int i=1;i<=n;i++)
{
if (i>1) ans=max(ans,t.maxxor(num[i]));
t.insert(num[i]);
}
}
};
namespace ANDOR
{
int f[V];
void pre(int l,int r)
{
if (l==r) return;
int mid=l+r>>1;
pre(l,mid),pre(mid+1,r);
for (int i=0;i<=mid-l;i++) f[l+i]+=f[mid+1+i];
}
void calc()
{
memset(f,0,sizeof f);
for (int i=1;i<=n;i++) f[num[i]]++;
pre(0,V-1);
ans=-1;
for (int i=1,cur,cst;i<=n;i++)
{
cur=cst=0;
for (int d=D-1;d>=0;d--)
if (c==3)
if (!((num[i]>>d)&1))
{
cst+=1<<d;
if (f[cst]) cur+=1<<d;
else cst-=1<<d;
}
else cur+=1<<d;
else
if ((num[i]>>d)&1)
{
cst+=1<<d;
if (f[cst]>1) cur+=1<<d;
else cst-=1<<d;
}
ans=max(ans,cur);
}
}
}
int main()
{
freopen("maximum.in","r",stdin),freopen("maximum.out","w",stdout);
for (T=read();T--;)
{
n=read(),c=read();
for (int i=1;i<=n;i++) num[i]=read();
if (c==2) XOR::calc();
else ANDOR::calc();
printf("%d\n",ans);
}
fclose(stdin),fclose(stdout);
return 0;
}