时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld
输入描述:
第一行一个整数N,表示序列的长度
第二行N个整数,表示序列内的元素
第三行一个整数q,表示询问的个数
接下来q行,每行两个整数[L, R],表示询问的区间
输出描述:
输出q行,每行一个整数表示答案
若有多组可行解,请输出较小的解
输入:
5
4 78 12 1 3
3
2 5
1 4
3 3
输出:
2147483632
2147483635
2147483635
思路:核心:贪心+前缀和
要让异或的结果尽可能的大,也就是尽量让每一位都是1。
自己举例后可以发现,当位置上1的数量多时,要去异或0,才能让结果为1,位置上0的数量多时,就要去异或1,让结果为1,优先满足大多数嘛~
因为结果相同时输出小的数,所以当0和1数量相同时,去异或0。自己做的时候用一下计算器,验证答案。
(代码有注释
//毒瘤xor
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int arr[100005][34];//前缀和
int b[34];//存 去异或 的那个数的二进制
int main()
{
int i,n,j,t;
ll x;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>x;
for(j=0;j<31;j++)
{
arr[i][j]=(x>>j)&1;//输入,存末尾数字
}
}
for(i=1;i<=n;i++)
for(j=0;j<31;j++)
arr[i][j]+=arr[i-1][j];//前缀和一波
cin>>t;
while(t--)
{
ll x,y;//
ll result=0;//结果
memset(b,0,sizeof(b));//每组新数据要清数组
cin>>x>>y;
cin.clear();
if(x==y)//如果区间只有一个数,特判
for(i=0;i<31;i++) b[i]=!(arr[x][i]-arr[x-1][i]);
else
for(i=0;i<31;i++)
{
if((arr[y][i]-arr[x-1][i])>(y-x)/2) b[i]=0;//如果0多,异或1
else b[i]=1;//反之
}
for(i=31;i>=0;i--) result+=b[i]*pow(2,i);//二转十 ,用一波pow
cout<<result<<endl;//输出结果
}
}