题解 | #毒瘤xor#

毒瘤xor

https://ac.nowcoder.com/acm/problem/18979

#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int n, q;
int arr[100010];
int arr_cnt[100010][31]={0};
int calc(int l, int r)
{   
    int x[32] = { 0 };
    for (int i = 0; i < 31; i++)
    {
        if (2*(arr_cnt[r][i]-arr_cnt[l-1][i]) >= r - l + 1)
        {
            x[i] = 0;
        }
        else
            x[i] = 1;
    }
    int res = 0;
    for (int i = 30; i >= 0; i--)
    {
        res *= 2;
        res += x[i];
    }
    return res;
}
int main()
{
    cin >> n;
    for (int i = 1; i <=n; i++)
    {
        int j=0;
        cin >> arr[i];
        int y = arr[i];
        while (y != 0)
        {
            if ((y & 1) == 1)
                arr_cnt[i][j]++;
            y >>= 1;
            j++;
        }
    }
    for(int i=2;i<=n+1;i++)
    {
        for(int j=0;j<31;j++)
            arr_cnt[i][j]+=arr_cnt[i-1][j];
    }
    cin >> q;
    int l;
    int r;
    for (int i = 0; i < q; i++)
    {
        cin >> l >> r;
        cout << calc(l, r) << endl;
    }
}

本题重要思想: 1、异或0不变,异或1取反 2、对于每一位单独考虑 3、要使异或后的和最大,应该尽量使每一位异或的结果1的个数多余0的个数,也由此决定了X在各位的值是1还是0。因此要预处理出每一位1的个数。 4、要注意本题时间限制,如果在每次计算时去求每一位1的个数,则会超时。因此最好预处理出序列中每个数在各位的0、1情况,再进行前缀和,这样在calc计算时只需要做个减法便能得出区间内各位1的个数。 5、输出X时可以用pow()函数,但更推荐像本题中从高位不断进行res *= 2;res += x[i];来输出。

全部评论

相关推荐

不愿透露姓名的神秘牛友
07-11 11:29
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务