Codeforces Round #430 (Div. 2) D - Vitya and Strange Lesson(补题,01Trie)

本文介绍了一种使用Trie树解决特定异或MEX问题的方法。该问题要求计算一组数字与给定数字异或后的MEX值。通过预处理未出现的数字并插入到Trie树中,可以高效查询每次异或操作后的最小未出现值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

调了好久,对着好多代码对了老半天,最终结果是数组开小了这里写图片描述。以前学Trie的时候学的是用结构体和指针的,对这种数组模拟的还真拿捏不好。
参考:http://blog.youkuaiyun.com/mengxiang000000/article/details/77718605
涨知识了,有学到了Trie的新用法。
题意就是给你n个数,询问m次,每次询问给你一个x,让你求这n个数异或x之后,查询这n个数字的mex,mex就是自然数中第一个没有出现过的数。当初看到这题,脑袋闪过的就是暴力过不去,除了暴力,别的还想不到。
思路:假设现在有0-(k-1)这k个不同的数字,从中抽出来n个数字作为输入的数字。这n个数字分别对x进行异或运算,得到了一个新的序列,这个序列的mex就是那(k-n)个数字中异或x的最小值。因为这k个数字,从中抽出来n个异或x,异或后的新序列中没出现过的数字肯定是那(k-n)个数字对x异或的值。

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

const int N = 19;
bool mark[1<<N];

struct Trie
{
    int next[(1<<N)*20][2];
    int sz;

    void init()
    {
        memset(next,-1,sizeof(next));
        sz = 0;
    }

    void insert(int num)
    {
        int cur = 0;
        for(int i = N-1; i >= 0; --i)
        {
            int t = (num>>i)&1;
            if(next[cur][t] == -1)
                next[cur][t] = ++sz;
            cur = next[cur][t];
        }
    }

    int query(int num)
    {
        int ret = 0;
        int cur = 0;
        for(int i = N-1; i >= 0; --i)
        {
            int t = (num>>i)&1;
            if(next[cur][t] != -1)
            {
                cur = next[cur][t];
                ret |= t<<i;
            }
            else
            {
                t = !t;
                cur = next[cur][t];
                ret |= t<<i;
            }
        }
        return ret;
    }
};
Trie t;
int main()
{
    t.init();
    int n,m,num;
    scanf("%d %d",&n,&m);
    for(int i = 0; i < n; ++i)
    {
        scanf("%d",&num);
        mark[num] = true;
    }
    for(int i = 0; i < (1<<N); ++i)
    {
        if(!mark[i])
            t.insert(i);
    }
    int q = 0;
    while(m--)
    {
        scanf("%d",&num);
        q ^= num;
        printf("%d\n",t.query(q)^q);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值