D. XOR Construction

D. XOR Construction

You are given n1 integers a1,a2,,an1.

Your task is to construct an array b1,b2,,bn such that:

  • every integer from 0 to n1 appears in b exactly once;
  • for every i from 1 to n1, bibi+1=ai (where denotes the bitwise XOR operator).

Input

The first line contains one integer n (2n2105).

The second line contains n1 integers a1,a2,,an1 (0ai2n).

Additional constraint on the input: it's always possible to construct at least one valid array b from the given sequence a.

Output

Print n integers b1,b2,,bn. If there are multiple such arrays, you may print any of them.

Examples

input

4
2 1 2

output

0 2 3 1 

input

6
1 6 1 4 1

output

2 3 5 4 0 1 

 

解题思路

  我的做法跟官方的基本一样。最关键的地方是要观察出 a 其实就是 b 的差分数组,假设下标都从 0 开始,即有 bi=b0a0a1ai1。主要是如果看到有 ai=bibi1 或者 ai=bibi1 就要想到对 a 求前缀和就会得到 b

  然而我们现在还不知到 b0,假设 c0=0ci=a0ai1,(i1),如果知道 b0 的话那么整个 b 数组都确定下来了,就是 b0 异或每个 ci。所以很自然想到枚举 0n1 来找到合法 b0,使得 b0 与每个 b0ci 恰好是 0n1 的全排列。如果直接暴力验证的话时间复杂度就是 O(n2),注意到题目保证存在解,所以可以分析一下 ci 具有什么性质。

  首先 ci 一定是成对不同的,否则假设 ci=cj,那么不管 b0 取什么必然有 cib0=cjb0,因此不可能存在解,矛盾。由于 ci 成对不同的,意味着 cib0 也是成对不同的,所以如果 max0in1{cib0}<n,那么此时 cib0 一定是 0n1 的全排列,此时的 b0 就是合法的解。

  为了快速得到 b0 与这些 ci 异或后的最大值是多少,可以将 ci 存到 trie 中,然后从最高位开始贪心选择即可。

  AC 代码如下,时间复杂度为 O(nlogn)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 10;

int a[N];
int tr[N * 19][2], idx;

void add(int x) {
    int p = 0;
    for (int i = 18; i >= 0; i--) {
        int t = x >> i & 1;
        if (!tr[p][t]) tr[p][t] = ++idx;
        p = tr[p][t];
    }
}

int query(int x) {
    int p = 0, ret = 0;
    for (int i = 18; i >= 0; i--) {
        int t = x >> i & 1;
        if (tr[p][!t]) {
            p = tr[p][!t];
            ret |= 1 << i;
        }
        else {
            p = tr[p][t];
        }
    }
    return ret;
}

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int x;
        scanf("%d", &x);
        a[i] = a[i - 1] ^ x;
        add(a[i]);
    }
    add(0);
    for (int i = 0; i < n; i++) {
        if (query(i) < n) {
            for (int j = 0; j < n; j++) {
                printf("%d ", a[j] ^ i);
            }
            break;
        }
    }
    
    return 0;
}

  再提供另外一种思路,按位考虑每一个 ci。对于二进制的第 k 位,如果每个 ci 的第 k 位共有 x1,数字 0n1 的第 k 位共有 y1,由于题目保证有解,因此如果 xy,那么只需让 b0 的第 k 位为 1 即可,否则为 0

  AC 代码如下,时间复杂度为 O(nlogn)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 10;

int a[N];

int main() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i < n; i++) {
        int x;
        scanf("%d", &x);
        a[i] = a[i - 1] ^ x;
    }
    int ret = 0;
    for (int i = 0; i <= 18; i++) {
        int s = 0;
        for (int j = 0; j < n; j++) {
            s += j >> i & 1;
            s -= a[j] >> i & 1;
        }
        if (s) ret |= 1 << i;
    }
    for (int i = 0; i < n; i++) {
        printf("%d ", a[i] ^ ret);
    }
    
    return 0;
}

 

参考资料

  Educational Codeforces Round 157 Editorial:https://codeforces.com/blog/entry/122034

  Educational Codeforces Round 157 (Rated for Div. 2):https://zhuanlan.zhihu.com/p/665022975

posted @   onlyblues  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示