思路
可以用位运算和前缀和的相关知识。
要让X异或a[i]求和最大SUM,则SUM的每一位都是1,我们需要求的是X的每一位该取0还是1。
我们可以用一个二维数组a[i][j]记录前i个数第j位是1的个数,这样我们就能知道L~R范围内某一位的0多还是1多。
运用异或的性质我们知道,在0多的情况下X那一位该取1,在1多的情况下X那一位该取0;
而0和1一样多的时候,根据题意X尽可能小,就取0。
代码
#include<bits/stdc++.h>
using namespace std;
int n,q,a,l,r;
int sm1[100005][32];
//sm[i][j]:第i个数前面第j位有多少个0/1;
int main(){
scanf("%d",&n);
memset(sm1,0,sizeof(sm1));
for(int i=1;i<=n;i++){
scanf("%d",&a);
int j=0;
while(a){
if(a&1) sm1[i][j]++;
a>>=1;
j++;
}
for(int j=0;j<=30;j++){ //求前缀和
sm1[i][j]+=sm1[i-1][j];
}
}
scanf("%d",&q);
for(int i=1;i<=q;i++){
scanf("%d%d",&l,&r);
int ans=0,len=r-l+1;
for(int j=0;j<=30;j++){
if(2*(sm1[r][j]-sm1[l-1][j])<len)
//l到r在j位上0的个数之和比1多,那么X的j位是1
ans+=(1<<j); //
}
cout<<ans<<endl;
}
return 0;
} 
京公网安备 11010502036488号