题目要求 最大,涉及到异或操作,很显然我们需要用位运算来处理这题
思路:
位运算时,每一个bit可以被独立的拿出来运算,所以我们记X的第p位bit为 ,区间里
的第p位bit为
,看看怎么让区间里
最大,也就是让区间里第p位bit上出现1的次数最多。
二进制中每一个bit不是0就是1,我们又知道异或运算 、
、
,想让一个bit变成1,那么参与运算的两个bit必须是一个0和一个1,区间里
都是固定的,所以我们需要改变
。
结合题目说明 “若有多组可行解,请输出较小的解”
这样我们就可以推断出:
- 当区间里第p位上1的数量大于0时,令
- 当区间里第p位上1的数量等于0时,令
,(输出较小的解)
- 当区间里第p位上1的数量小于0时,令
这样对每一个处理完以后,就得到了符合题意的
当然,如果每一次询问都数一下出现了多少次1的话计算量 可能 有点大,所以下面用了前缀和
*把DEBUG改成1会输出nums和bit
#include <iostream>
#include <memory.h>
#include <algorithm>
#define DEBUG 0
using namespace std;
int main() {
int N; //序列长度
cin >> N;
int nums[N + 1]; //a1~aN
int bit[N + 1][33]; //a1~aN的二进制各个位中1出现的次数(从右往左数)
memset(nums, 0, sizeof(nums));
memset(bit, 0, sizeof(bit));
for (int i = 1; i <= N; ++i) {
cin >> nums[i];
for (int j = 0; j <= 31; ++j) {
bit[i][j + 1] = bit[i - 1][j + 1];
if (nums[i] & (1 << j))bit[i][j + 1]++;
}
}
//输出nums
if (DEBUG) {
cout << "nums: ";
for (int i = 1; i <= N; ++i) {
cout << nums[i] << " ";
}
cout << endl;
}
//输出bit
if (DEBUG) {
cout << "bit: " << endl;
for (int i = 0; i <= N; ++i) {
cout << "[" << i << "]: ";
for (int j = 32; j >= 1; --j) {
cout << bit[i][j] << " ";
}
cout << "( " << nums[i] << " )" << endl;
}
cout << endl;
}
int q; //询问的次数
cin >> q;
for (int i = 0; i < q; ++i) {
int L, R; //区间端点(闭区间)
cin >> L >> R;
int X = 0; //解
for (int j = 31; j >= 1; --j) {
if (bit[R][j] - bit[L - 1][j] < (R - L + 1) / 2.0) {
X += (1 << (j - 1));
}
}
cout << X << endl;
}
}
京公网安备 11010502036488号