ACM-ICPC 2017 Asia Xi’an
A. XOR ACM-ICPC 2017 Asia Xi’an
题意:给定N个数和Q个询问,每次在[L,R]区间内取一些数,使得与K异或的值最大,问这个值时多少
思路:与K异或使得结果变大,从二进制的角度考虑,就是把k的二进制中为0的位置尽量变为1。所以先将K取反,对A[i]&K,建立线性基,最后取最大值
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define ls (rt<<1)
#define rs ((rt<<1)|1)
#define ll long long
using namespace std;
const int maxn=1e5+10,INF=0x3f3f3f3f;
const int mod=1e9+7;
ll t,N,Q,K;
ll a[maxn];
struct LinearBase
{
ll base[66];
int cnt;
LinearBase()
{
memset(base,0,sizeof(base));
cnt=0;
}
void init()
{
memset(base,0,sizeof(base));
cnt=0;
}
bool Insert(ll x)
{
for(int i=60;i>=0;--i)
{
if(x&(1ll<<i))
{
if(!base[i])
{
base[i]=x;
break;
}
x^=base[i];
}
}
return x>0;
}
ll QueryMax()
{
ll ret=0;
for(int i=60;i>=0;--i)
if((ret^base[i])>ret)
ret^=base[i];
return ret;
}
ll QueryMin()
{
for(int i=0;i<=60;++i)
if(base[i])
return base[i];
return 0;
}
bool find(ll x)
{
for(int i=32;i>=0;--i)
{
if(x&(1ll<<i))
{
if(!base[i])
break;
x^=base[i];
}
}
return x==0;
}
}ST[maxn<<2];
LinearBase Merge(const LinearBase &a,const LinearBase &b)
{
LinearBase ret=a;
for(int i=60;i>=0;--i)
if(b.base[i])
ret.Insert(b.base[i]);
return ret;
}
void Push_up(int rt)
{
ST[rt]=Merge(ST[ls],ST[rs]);
}
void Build(int rt,int L,int R)
{
ST[rt].init();
if(L==R)
{
ST[rt].Insert(a[L]);
return;
}
int mid=(L+R)>>1;
Build(ls,L,mid);
Build(rs,mid+1,R);
Push_up(rt);
}
LinearBase Query(int rt,int l,int r,int L,int R)
{
if(l<=L&&R<=r)
return ST[rt];
int mid=(L+R)/2;
if(r<=mid)
return Query(ls,l,r,L,mid);
else if(l>mid)
return Query(rs,l,r,mid+1,R);
else
return Merge(Query(ls,l,r,L,mid),Query(rs,l,r,mid+1,R));
}
int main()
{
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&N,&Q,&K);
K=~K;
for(int i=1;i<=N;++i)
{
scanf("%lld",&a[i]);
a[i]=(a[i]&K);
}
K=~K;
Build(1,1,N);
while(Q--)
{
int l,r;
scanf("%d%d",&l,&r);
LinearBase lb=Query(1,l,r,1,N);
ll ans=lb.QueryMax();
printf("%lld\n",(ans|K));
}
}
return 0;
}
/*
1
5 3 0
1 2 3 4 5
1 3
2 4
3 5
*/