[Atcoder]arc92 D - Two Sequences(二进制+二分)

D - Two Sequences

题目链接:

D - Two Sequences

题目大意:

给两个数组长度为n的数组A, B。 计算所有 A[i]+B[j] 的异或和。

数据范围:

1n2·105
0ai,bi228


解题思路:

比赛的时候这道题我没有做出来, 只能想到按位拆分, 但是拆完了之后就不知道如何批量处理了。
看了官方的题解和百度上其他大佬的题解, 才理解清楚。
按照官方题解的说法, 首先我没枚举一个2的x次幂T, 对于所有的数, 我们只要%(2*T)就可以截取二进制下x位。
对于任意两个 ai,bj 满足第x为相加为1的条件是 Tai+bj<2T 或者 3Tai+bj<4T 。 那么对于一个数值 ai 我们将b数组排序, 通过二分找到满足条件的区间个数。 即可算出最后x位1的个数, 根据奇偶是奇数个则最后的异或和有贡献。

AC代码:

/********************************************
 *Author*        :ZZZZone
 *Created Time*  : 一  3/26 10:54:23 2018
 * Ended  Time*  : 一  3/26 11:03:05 2018
*********************************************/

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <stack>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;

inline void OPEN(string s){
    freopen((s + ".in").c_str(), "r", stdin);
    freopen((s + ".out").c_str(), "w", stdout);
}

int main()
{
    //OPEN("arc92-d");
    int n;
    scanf("%d", &n);
    vector<int> a(n), b(n);
    for(int i = 0; i < n; i++) scanf("%d", &a[i]);
    for(int i = 0; i < n; i++) scanf("%d", &b[i]);
    vector<int> c, d;
    int ans = 0;
    int pow_2 = 1;
    for(int i = 0; i <= 28; i++){
        c = a, d = b;
        for(int j = 0; j < n; j++){
            c[j] %= 2 * pow_2;
            d[j] %= 2 * pow_2;
        }
        sort(c.begin(), c.end());
        sort(d.begin(), d.end());
        int l, r, sum = 0;
        for(int j = 0; j < n; j++){
            l = lower_bound(d.begin(), d.end(), pow_2 - c[j]) - d.begin();
            r = lower_bound(d.begin(), d.end(), 2*pow_2 - c[j]) - d.begin() - 1;
            sum += (r-l+1);
            l = lower_bound(d.begin(), d.end(), 3*pow_2 - c[j]) - d.begin();
            r = lower_bound(d.begin(), d.end(), 4*pow_2 - c[j]) - d.begin() - 1;
            sum += (r-l+1);
        }
        if(sum & 1) ans += pow_2;
        pow_2 *= 2;
    }
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zzzzone/article/details/79701785