题解 | #毒瘤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];来输出。

全部评论

相关推荐

白火同学:1、简历可以浓缩成一页,简历简历先要“简”方便HR快速过滤出有效信息,再要“历”用有效信息突出个人的含金量。 2、教育背景少了入学时间~毕业时间,HR判断不出你是否为应届生。 3、如果你的平台账号效果还不错,可以把账号超链接或者用户名贴到对应位置,一是方便HR知道你是具体做了什么内容的运营,看到账号一目了然,二是口说无凭,账号为证,这更有说服力。
面试被问期望薪资时该如何...
点赞 评论 收藏
分享
程序员花海_:抓紧时间去找实习 项目其实只是玩具项目 脱离业务很远的
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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