牛客竞赛 1032 毒瘤xor
题意
给定\(n\)个整数组成的数组\(a_1...a_n\) , 每次给出一个区间\([l,r]\) , 找到小于\(2^{31}\)的最小非负整数\(x\) ,使得
\[\sum_{i=l}^{r}(x \oplus a_i)
\]
最大
思路
这题总是感觉似曾相识
按位考虑 , 从最高位(31)到最低位(0) , 如果\(1\)的数量多 , 那么就设置\(a_i\)为\(0\) , 否则设置为\(0\)
那么如何快速求出\([l,r]\)区间中第\(pos\)位的1和0的个数捏 ?
前缀和
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long int
inline int read() {
int ans = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0') {
ans = ans * 10 + ch - '0';
ch = getchar();
}
return ans * f;
}
const int N = 1e5+10;
int a[N];
int presum[N][35];
signed main() {
int n =read();
for (int i = 1; i<= n; i++) {
a[i] =read();
}
for (int i = 1; i<= n; i++) {
for (int j = 30; j>=0; j--) {
presum[i][j] = presum[i-1][j] + (a[i]>>j&1);
//只用算1的个数就行啦
}
}
int q=read();
while (q--) {
int ans = 0;
int l=read(),r=read();
for (int i = 30; i>= 0; i--) {
ans <<=1;
int cnt1 = presum[r][i] - presum[l-1][i];
if (cnt1 >= (r-l+2)>>1) {
ans+=0;
}
else
ans += 1;
}
cout<<ans<<"\n";
}
return 0;
}

浙公网安备 33010602011771号