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

    题意:一个序列(n<3e5),m个查询,每次序列所有的数亦或x,问这个序列的mex(mex定义是最小没有出现过的非负整数),保留每一次的更改

    题解:首先要知道mex怎么求,把每一个数分解为二进制,按高位到低位进行建一颗二叉树,可以o(logn)查询到mex

    其次要知道异或有结合率,也就是求一个前缀就可以了

    分解每次查询的数,从高位到低位遍历,遍历到该为为bit,判断sum[(t<<1)+bit]这棵树有没有装满,装满的话就答案就在另一棵树

    #include <bits/stdc++.h>
    #define ll long long
    #define maxn 300100
    int a[maxn], n, m, sum[1<<20];
    using namespace std;
    void build(){
        for(int i=0;i<n;i++){
            bitset<19>bit(a[i]);
            int t = 1;
            for(int i=18;i>=0;i--){
                if(bit[i] == 0) t = t*2;
                else t =t*2+1;
            }
            sum[t] = 1;
        }
        for(int i=(1<<20)-1;i>=1;i--)
            sum[i>>1] += sum[i];
    }
    int query(int temp){
        bitset<19>bit(temp);
        int t = 1, ans = 0, cnt;
        for(int i=18;i>=0;i--){
            cnt = (1<<i);
            ans = ans*2;
            if(bit[i] == 0){
                if(sum[t<<1] == cnt) t = t<<1|1, ans++;
                else t = t<<1;
            }
            else{
                if(sum[t<<1|1] == cnt) t = t<<1, ans++;
                else t = t<<1|1;
            }
        }
        return ans;
    }
    int main(){
        scanf("%d%d", &n, &m);
        for(int i=0;i<n;i++) scanf("%d", &a[i]);
        build();
        int temp = 0;
        while(m--){
            scanf("%d", &n);
            temp ^= n;
            printf("%d
    ", query(temp));
        }
        return 0;
    }
  • 相关阅读:
    网线 ------ 交叉线
    ubuntu ------ 网络 ifconfig 不显示IP地址
    STM32L011D4 ----- 低功耗
    List 集合 使用 remove 踩得坑
    Map 集合遍历的4种方法
    elasticsearch 集群详解
    谷歌浏览器添加插件时显示程序包无效:"CRX_HEADER_INVALID" 解决办法
    MySql数据库 优化
    MySql 索引
    Kibana 安装
  • 原文地址:https://www.cnblogs.com/Noevon/p/7460915.html
Copyright © 2011-2022 走看看