zoukankan      html  css  js  c++  java
  • zr#956 集合

    分析

    我们发现+1操作就是对于一段连续的1找到它前面最近的0

    将这一整段每个数都异或1

    我们可以在01trie上走将每一个合法点拿出来打上标记

    然后最后依次交换所有标记点的左右儿子即可

    我们继续考虑带异或的问题

    我们发现我们可以存一下之前的总异或值

    然后所有操作前把数跟这个数异或一下即可

    代码

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,trie[10000000][2],siz[10000000],cnt,all,d[10000000],res;
    int ans[10000000],sum;
    inline void ins(int x,int k){
        int i,j,p=0;
        for(i=0;i<30;i++){
          int wh=(x&(1<<i))?1:0;
          siz[p]+=k;
          if(!trie[p][wh])trie[p][wh]=++cnt;
          p=trie[p][wh];
        }
        siz[p]+=k;
    }
    inline void rev(){
        int i,j,x=((1<<30)-1)^all,p=0;
        res=0;
        for(i=0;i<30;i++){
          int wh=(x&(1<<i))?1:0;
          d[++res]=p;
          p=trie[p][wh];
          if(!p)break;
        }
        for(i=1;i<=res;i++)swap(trie[d[i]][0],trie[d[i]][1]);
    }
    inline void dfs(int p,int x,int wh){
        if(!siz[p])return;
        if(!trie[p][0]&&!trie[p][1]){
          for(int i=1;i<=siz[p];i++)ans[++sum]=x^all;
          return;
        }
        if(trie[p][0])dfs(trie[p][0],x,wh+1);
        if(trie[p][1])dfs(trie[p][1],x+(1<<(wh+1)),wh+1);
    }
    int main(){
        int i,j,k;
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++){
          int x;
          scanf("%d",&x);
          ins(x,1);
        }
        for(i=1;i<=m;i++){
          int x;
          scanf("%d",&k);
          if(k==1)scanf("%d",&x),ins(x^all,1);
            else if(k==2)scanf("%d",&x),ins(x^all,-1);
            else if(k==3)rev();
            else scanf("%d",&x),all^=x;
        }
        dfs(0,0,-1);
        sort(ans+1,ans+sum+1);
        for(i=1;i<=sum;i++)printf("%d ",ans[i]);
        puts("");
        return 0;
    }
  • 相关阅读:
    Rocky Linux8国内镜像源
    强制缓存和协商缓存的区别
    从源码来看VUE的执行流程
    plugin
    判断数据类型的方法
    获取函数参数
    BFC
    VUE的$nextTick
    HTTP
    JavaScript创建和触发自定义事件
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/11470880.html
Copyright © 2011-2022 走看看