码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1322B - Present

时间:2020-06-14 14:56:33      阅读:47      评论:0      收藏:0      [点我收藏+]

标签:onclick   names   code   归并   esc   click   int   empty   amp   

Description

给出序列 $a_i$, 求两两之和的异或值 


Solution

按位计算
计算到第 $k$ 位时,将 $a_i$ 按 $mod \ 2^{k+1}$ 后排序
当 $a_i \ mod \ 2^{k+1} + a_j \ mod \ 2^{k+1}\in [2^k, \ 2^{k+1} - 1] \cup [2^{k + 1} + 2^k, 2^{k+2}-2]$, 这两数和的第 $k$ 位为 $1$
排序时每次加入一位重排可用归并排序,找区间可以用双指针
复杂度$O(n log Max)$


Code

技术图片
#include <bits/stdc++.h>
using namespace std;


inline int read() {
    int out = 0;
    bool flag = false;
    register char cc = getchar();
    while (cc < 0 || cc > 9) {
        if (cc == -) flag = true;
        cc = getchar();
    }
    while (cc >= 0 && cc <= 9) {
        out = (out << 3) + (out << 1) + (cc ^ 48);
        cc = getchar();
    }
    return flag ? -out : out;
} 

inline void write(int x) {
    if (x < 0) putchar(-), x = -x;
    if (x == 0) putchar(0);
    else {
        int num = 0;
        char cc[15];
        while (x) cc[++num] = x % 10 + 48, x /= 10;
        while (num) putchar(cc[num--]);
    }
    putchar(\n);
}


int N, a[400010], b[400010], l1, r1, l2, r2, cnt, ans;

queue<int> q1, q2; 

int main() {
    N = read();
    for (int i = 1; i <= N; i++) a[i] = read(), b[i] = i;
    for (int k = 0; k <= 24; k++) {
        for (int i = 1; i <= N; i++) 
            if (a[b[i]] & (1 << k)) q1.push(b[i]);
            else q2.push(b[i]);
        int o = 0; 
        while (!q2.empty()) b[++o] = q2.front(), q2.pop();
        while (!q1.empty()) b[++o] = q1.front(), q1.pop();
        l1 = l2 = N + 1, r1 = r2 = N, cnt = 0;
        int Mod = (1 << (k + 1)) - 1;
        for (int i = 1; i <= N; i++) {
            o = (a[b[i]] & Mod);
            while (l1 >= 2 && o + (a[b[l1 - 1]] & Mod) >= (1 << k)) l1--;
            while (r1 >= 1 && o + (a[b[r1]] & Mod) >= (1 << (k + 1))) r1--;
            while (l2 >= 2 && o + (a[b[l2 - 1]] & Mod) >= (1 << (k + 1)) + (1 << k)) l2--;
            while (r2 >= 1 && o + (a[b[r2]] & Mod) >= (1 << (k + 2)) - 1) r2--;
            if (max(i + 1, l1) <= r1) cnt += r1 - max(i + 1, l1) + 1;
            if (max(i + 1, l2) <= r2) cnt += r2 - max(i + 1, l2) + 1;
        }
        if (cnt & 1) ans |= 1 << k;
    }
    write(ans);
    return 0;
}
View Code

 

Codeforces 1322B - Present

标签:onclick   names   code   归并   esc   click   int   empty   amp   

原文地址:https://www.cnblogs.com/Urushibara-Ruka/p/13124428.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!