时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld
题目描述
输入描述:
第一行一个整数N,表示序列的长度 第二行N个整数,表示序列内的元素 第三行一个整数q,表示询问的个数 接下来q行,每行两个整数[L,
R],表示询问的区间
输出描述:
输出q行,每行一个整数表示答案
若有多组可行解,请输出较小的解
示例1
输入
复制
5
4 78 12 1 3
3
2 5
1 4
3 3
输出
2147483632
2147483635
2147483635
备注:
对于30%的数据,n , q ≤ 10
对于60%的数据,n , q ≤ 1000
对于100%的数据,n, q ≤ 10^5
保证ai < 2^31
题解:
很久没有遇到异或的题了
先讲下异或:1 ^ 1 =0 , 0 ^ 0= 0,1 ^ 0 =1,0 ^ 1 =1
相同为0,不同为1
异或是两个数二进制状态下相同数位进行操作
我们要找一个x使得x ^ a[i]的和最大,那我们就尽量使x与a[i]的相同位数异或后为1,这样就最大
a[i]是一个数组,所以我们就求这个数组里每个数的二进制状态下,每一位0和1的个数,比如说,数组有n个数,其中b个数二进制状态下第一位是0,剩下n-b个数二进制状态下第一位是1,如果b>n-b,那我们就使X二进制的第一位是1,(就是和最多情况的数呈相反,这样异或出来才是1)
然后是第二位,依次类推最后我们就得到X的二进制状态,转化成十进制输出即可
因为有多轮询问,所以我们可以用前缀和来处理每一位为1的数
bool w=((a[i]>>j)&1);//判断第j位是0是1
sum[i][j]=(sum[i-1][j]+w);//前缀和进行累加
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+4;
typedef long long ll;
ll a[maxn];
int sum[maxn][40];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
for(int i=1;i<=n;i++)
{
for(int j=0;j<31;j++)
{
bool w=((a[i]>>j)&1);//判断第j位是0是1
sum[i][j]=(sum[i-1][j]+w);
}
}
int q;
cin>>q;
int tot=0;
while(q--)
{
tot=0;
int l,r;
cin>>l>>r;
for(int j=0;j<31;j++)
{
if(sum[r][j]-sum[l-1][j] < ( (r-l)/2+1) )//当这一位0居多时,X选为1
tot+=(1<<j);
}
cout<<tot<<endl;
}
}