牛客竞赛 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;
}
posted @ 2025-06-21 00:47  Guaninf  阅读(6)  评论(0)    收藏  举报