zoukankan      html  css  js  c++  java
  • NOIP模拟-----位运算

    题目

    有q次操作,每次操作是以下两种:
    1、 加入一个数到集合中
    2、 查询,查询当前数字与集合中的数字的最大异或值,最大and值,最大or值
    输入
    第一行1个正整数Q表示操作次数
    接下来Q行,每行2个数字,第一个数字是操作序号OP(1,2),第二个数字是X表示操作的数字
    输出
    输出查询次数行,每行3个整数,空格隔开,分别表示最大异或值,最大and值,最大or值
    样例输入
    【输入样例1】
    5
    1 2
    1 3
    2 4
    1 5
    2 7
    【输出样例1】
    7 0 7
    5 5 7
    【样例解释1】
    询问4时,已插入2、3,最大异或值为4^3=7,最大and值为4&3或4&2=0,最大or值为4|3=7
    询问7时,已插入2、3、5,最大异或值为7^2=5,最大and值为7&5=5,最大or值为7|2=7|3=7|5=7
    【输入样例2】
    10
    1 194570
    1 202332
    1 802413
    2 234800
    1 1011194
    2 1021030
    2 715144
    2 720841
    1 7684
    2 85165
    【输出样例2】
    1026909 201744 1032061
    879724 984162 1048062
    655316 682376 1043962
    649621 683464 1048571
    926039 85160 1011199
    样例输出 [复制]
    提示
    对于%10的数据1<=Q<=5000
    对于另%10的数据保证 X<1024
    对于另%40的数据保证1<=Q<=100000
    对于所有数据保证1<=Q<=1000000,1<=X<=2^20 保证第一个操作为1操作。

    异或操作很简单,建trie树就是了,而&和 | 可以按位贪心

    比如&时,如果x该位已为0,那么0和1都是可以的,于是只需要给子集打标记,默认填0

    |也是基本上一样的

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int q,trans[(1<<21)+3][2],tot=1,op,x;
    inline int read(){
        char ch;
        while((ch=getchar())<'0'||ch>'9'){;}
        int res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')
        res=res*10+ch-'0';
        return res;
    }
    int le[1<<20];
    inline void mark(int x)
    {
        le[x]=1;
        for(int i=0;i<20;i++)
        {
            if((x>>i&1)&&(!le[x^(1<<i)])) mark(x^(1<<i));
        }
    }
    inline void insert(int k)
    {
        int p=1;
        for(int i=19;~i;i--)
        {
            int c=(k>>i&1?1:0);
            if(!trans[p][c]) trans[p][c]=++tot;
            p=trans[p][c];
        }
    }
    inline int find(int k)
    {
        int p=1,now=0;
        for(int i=19;~i;i--)
        {
            int c=(k>>i&1?0:1);
            if(trans[p][c])
            {
                p=trans[p][c];
                if(c)
                now|=1<<i;
            }
            else
            {
                p=trans[p][c^1];
                if(c^1) now|=1<<i;
            }
        }
        return now;
    }
    int main(){
        q=read();
        for(int o=1;o<=q;o++)
        {
            op=read(),x=read();
            if(op==1)
            {
                mark(x);
                insert(x);
            }
            else
            {
                printf("%d ",find(x)^x);
                int now=0;
                for(int i=19;~i;i--)
                {
                    if((x>>i&1)&&le[now|1<<i]) now|=1<<i;
                }
                printf("%d ",now&x);
                now=0;
                for(int i=19;~i;i--)
                {
                    if((!(x&(1<<i)))&&le[now|1<<i]) now|=1<<i;
                }
                printf("%d
    ",now|x);
            }
        }
    }
  • 相关阅读:
    杂题
    [ AtCoder Grand Contest 031] C
    [ AtCoder Regular Contest 107 ] C
    [ 实验舱 CSP/NOIP新赛制内部挑战赛4 ] 树上询问
    [ 2020牛客NOIP赛前集训营-提高组(第六场) ] 补题
    [NOI Online #2 提高组]子序列问题
    洛谷P4317 花神的数论题
    [AHOI2009]同类分布
    洛谷P3413 SAC#1
    数位dp小结
  • 原文地址:https://www.cnblogs.com/forever-/p/9736088.html
Copyright © 2011-2022 走看看