NC18979 毒瘤xor

题目

题目描述

小a有 N 个数 a1,a2,...,aN ,给出 q 个询问,每次询问给出区间 [L,R] ,现在请你找到一个数 X ,使得

  1. 0X<231
  2. i=LRXa[i] 最大, 表示异或操作(不懂的请自行百度)

输入描述

第一行一个整数 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,q10
对于 60% 的数据,n,q1000

对于 100% 的数据,n,q105
保证 ai<231

题解

知识点:贪心,位运算。

显然不能每次枚举,需要更快的贪心方法构造一个 X

对于位运算的贪心,只需要让每位到达最优就行,因为互相独立。因此,本题只要对于 X 的每一位产生的和最大即可。

考察所有 ai 某一位,要让这位异或和最大,就要考虑这位的 10 的数量,如果 1 多,则 X 这位应为 0 ,否则为 1 。这里可以用二维数组 sum[i][j] 代表 [1,i] 的数字中第 j 位是 1 的数量,前缀和预处理即可。

但要注意的是,我们要求最小的 X ,因此在两者皆可时 0 更优,即 1 的数量为严格小于一半时就用 1。这里不能用 sum[r][i] - sum[l - 1][i] < (r - l + 1)/2 ,因为这是取下整,要取上整。

时间复杂度 O(n+q)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
using namespace std;
int a[100007], sum[100007][31];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
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++) {
if (a[i] & (1 << j)) sum[i][j]++;
sum[i][j] += sum[i - 1][j];
}
}
int q;
cin >> q;
while (q--) {
long long l, r;
cin >> l >> r;
int x = 0;
for (int i = 0;i < 31;i++) {
if (2 * (sum[r][i] - sum[l - 1][i]) < r - l + 1) x |= (1 << i);///这里要除的话取上整
}
cout << x << '\n';
}
return 0;
}
posted @   空白菌  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示