zoukankan      html  css  js  c++  java
  • D. Vitya and Strange Lesson

    http://codeforces.com/contest/842/problem/D

    1、整体的数组是不用变的,比如数组a[]经过一次询问x后,然后再询问y,相当于询问x ^ y ^ a[i]后的mex值

    2、假设所求的答案是k,询问的数字是x,那么对于每个元素a[i],有a[i] ^ x != k恒成立。因为k是一个a[i]^x后得到的新数组,一个不存在新数组的数。所以若a[i] ^ x = k,则k不会是答案。

    3、两个数相异或的结果是唯一的,即z ^ x 是一个确定值。

    那么要求答案k,我肯定能找到一个数b,这个数不属于a[],使得别b ^ x = k

    所以就相当于找一个数,异或x,得到的值最小,就是答案。

    数b的范围是a[]的补集,因为a[]是3e5,所以补集大小开到1e6就够,不然这题用这个方法是做不了的。据说有一个好方法,但是还没想懂。

    为什么最小是答案,因为数b[]异或x的结果肯定不会和a[]异或x的结果相同。证明:

    若b[i] ^ x == a[i] ^ x,那么同时异或x,就等于b[i] = a[i]矛盾。

    所以数b[]异或x的结果,每一个都是a[]异或x的结果中不存在的数。

    那么找最小的那个就当然是答案

    #include <bits/stdc++.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    const int maxn = 1e6 + 20;
    int vis[maxn];
    struct Node {
        struct Node *pNext[2];
    } tree[maxn * 30];
    int t;
    struct Node *create() {
        struct Node *p = &tree[t++];
        for (int i = 0; i < 2; ++i) p->pNext[i] = NULL;
        return p;
    }
    void toInsert(struct Node **T, int val) {
        struct Node *p = *T;
        if (p == NULL) p = *T = create();
        for (int i = 25; i >= 0; --i) {
            int id = ((1 << i) & val) > 0;
            if (p->pNext[id] == NULL) p->pNext[id] = create();
            p = p->pNext[id];
        }
    }
    int ask(struct Node *T, int val) {
        struct Node *p = T;
        LL ans = 0;
        for (int i = 25; i >= 0; --i) {
            int id = ((1 << i) & val) > 0;
            if (p->pNext[id]) p = p->pNext[id];
            else {
                if (!p->pNext[!id]) return ans + (1 << i);
                ans += 1 << i;
                p = p->pNext[!id];
            }
        }
        return ans;
    }
    void work() {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; ++i) {
            int x;
            scanf("%d", &x);
            vis[x] = true;
        }
        struct Node *T = NULL;
        for (int i = 0; i <= maxn - 20; ++i) {
            if (!vis[i]) toInsert(&T, i);
    //        printf("%d
    ", i);
        }
        int haha = 0;
        for (int i = 1; i <= m; ++i) {
            int val;
            scanf("%d", &val);
            haha ^= val;
            printf("%d
    ", ask(T, haha));
        }
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
    //    printf("%d
    ", 1 << 25);
        work();
        return 0;
    }
  • 相关阅读:
    Dom4J总结
    使用API修改控制台输出的颜色(前景色和背景色)
    小程序[邮箱提取器-EmailSplider]总结
    双击jar不能运行的解决方法
    VMware10中安装centos7没有可用的网络设备
    SynEdit(Delphi XE7)的安装和基本使用
    http协议的构成及字段说明(请求头、请求体、响应头)
    jmeter中JSON Extractor用法
    selenium+python3模拟键盘实现粘贴、复制
    python3操作MySQL实现数据驱动完整实例
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7467558.html
Copyright © 2011-2022 走看看