CodeForces 842D Vitya and Strange Lesson

题目:http://codeforces.com/problemset/problem/842/D

题意:给你n个数,m次查询,每次将数组全部异或一个数后,求没出现过的最小自然数

要求异或后的最小值我们可以用字典树来解决

而每次对数组异或可以替换每次对异或值异或

之后贪心的选取

每次都走左子树,如果左子树满了,才走右子树,这样就能保证是最小

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
int a[20][1<<19];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if (!a[0][x])//去重
            for(int j=0;j<20;j++)
                a[j][x>>j]++;
    }
    x=0;
    while(m--)
    {
        int y;
        scanf("%d",&y);
        x^=y;
        int ans=0;
        for(int i=19;i>=0;i--)
            if (a[i][(ans^x)>>i]==1<<i) ans|=1<<i;//左子树满了,走右子树
        printf("%d\n",ans);
    }
    return 0;
}

  

时间: 2024-08-27 18:24:48

CodeForces 842D Vitya and Strange Lesson的相关文章

Codeforce842D Vitya and Strange Lesson

题意:一个序列(n<3e5),m个查询,每次序列所有的数亦或x,问这个序列的mex(mex定义是最小没有出现过的非负整数),保留每一次的更改 题解:首先要知道mex怎么求,把每一个数分解为二进制,按高位到低位进行建一颗二叉树,可以o(logn)查询到mex 其次要知道异或有结合率,也就是求一个前缀就可以了 分解每次查询的数,从高位到低位遍历,遍历到该为为bit,判断sum[(t<<1)+bit]这棵树有没有装满,装满的话就答案就在另一棵树 #include <bits/stdc++

cf842d Vitya and Strange Lesson

#include <iostream> #include <cstdio> using namespace std; int s[2000005][2], cnt, n, m, x, uu, ans, dep[2000005], siz[2000005]; void ins(){ int u=0; for(int i=19; i>=0; i--){ int t=(x&(1<<i))>0; if(!s[u][t]) s[u][t] = ++cnt; u

Codeforces Gym 101138 D. Strange Queries

Description 给你一下长度为 \(n\) 的序列. \(a_i=a_j\) \(l_1 \leqslant i \leqslant r_1\) \(l_2 \leqslant i \leqslant r_2\) 询问满足条件的 \((i,j)\) 对数. Sol 分块+前缀和. 非常乱搞啊... 首先分块 \(O(\sqrt{n})\) 一块. 然后在每块里统计块中元素出现次数. 先预处理块与块之间的贡献,然后处理不足一块的. 处理块与块之间的时候,需要前缀和优化一下就可以了,枚举当前

CodeForces 718A Efim and Strange Grade (贪心)

题意:给定一个浮点数,让你在时间 t 内,变成一个最大的数,操作只有把某个小数位进行四舍五入,每秒可进行一次. 析:贪心策略就是从小数点开始找第一个大于等于5的,然后进行四舍五入,完成后再看看是不是还可以,一循环下去,直到整数位,或者没时间了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <

CodeForces 719A Vitya in the Countryside (水题)

题意:根据题目,给定一些数字,让你判断是上升还是下降. 析:注意只有0,15时特别注意一下,然后就是14 15 1 0注意一下就可以了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostr

CodeForces 719A Vitya in the Countryside 思维题

题目大意:月亮从0到15,15下面是0.循环往复.给出n个数字,如果下一个数字大于第n个数字输出UP,小于输出DOWN,无法确定输出-1. 题目思路:给出0则一定是UP,给出15一定是DOWN,给出其他的一个数字(n==1)无法确定,其他的情况比较后两位. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 #include<stdio.

Codeforces 1190D. Tokitsukaze and Strange Rectangle

传送门 注意到矩形往上是无限的,考虑把点按 $y$ 从大到小考虑 对于枚举到高度为 $h$ 的点,设当前高度大于等于 $h$ 的点的所有点的不同的 $x$ 坐标数量为 $cnt$ 那么对于这一层高度 $h$ 我们就有 $cnt(cnt+1)/2$ 种不同的 $l$,$r$ ,使得矩形内点集不同 发现对于某些 $x$ 在这一层相邻两点之间,高度大于 $h$ 的点,这样又重复算了它们的贡献,所有要再扣掉 直接用树状数组维护一下当前区间内不同的 $x$ 的数量即可 因为离散化了判断 $x$ 是否出现过

01-trie练习

一般习惯用递归实现01-trie, 可以看做是区间长度为2的幂的权值线段树, 能实现权值线段树的所有操作, 同时还可以实现一些异或操作 const int N = 1<<20; struct {int ch[2],sum;} tr[N<<1]; void ins(int &o, int d, int x) { if (!o) o=++tot; ++tr[o].sum; if (d>=0) ins(tr[o].ch[x>>d&1],d-1,x); }

【Codeforces Round #430 (Div. 2) A C D三个题】

·不论难度,A,C,D自己都有收获! [A. Kirill And The Game] ·全是英文题,述大意:    给出两组区间端点:l,r,x,y和一个k.(都是正整数,保证区间不为空),询问是否在[x,y]区间内存在一个整数p,使得p*k属于[l,r],如果存在,则输出'YES',否则输出'NO'.(1<=l,r,x,y<=107) ·分析:     首先看见了107,发现可以直接O(n)暴力枚举:枚举区间[x,y]的所有数,判断它与k的乘积是否在[l,r]中就可以了.从容AC: