zoukankan      html  css  js  c++  java
  • [NOI2017]整数

    https://www.luogu.org/problemnew/show/P3822

    题解

    如果只有加法没有减法,那么我们朴素进位的时间复杂度是均摊(O(1))的。

    那么减法的话我们维护一个增量的数,一个减量的数,就是一个存所有(a>0)的变量,一个存所有(a<0)的变量。

    那么我们考虑一个位置的数是(0)还是(1),我们先对这个位置做个减法,然后唯一对这个值有影响的就是低位是否有借位,如果有,这一位就翻转。

    那么问题就转化为比较两个数的大小,用set维护不一样的位置就行了。

    然后这道题的范围是(30n),所以我们可以把每(30)个位压成一个(int)存就可以了,每次只会对两个位置进行修改。

    注意,提取一个负数的某个二进制位的时候可能会出问题,最好把它搞成正的再去做。

    代码

    #include <bits/stdc++.h>
    #define N 1000002
    using namespace std;
    typedef long long ll;
    typedef unsigned int u;
    int maxn=1000000;
    int n,t1,t2,t3;
    u z[N],f[N];
    bool cun[N];
    set<int>s;
    inline ll rd(){
      ll x=0;char c=getchar();bool f=0;
      while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
      while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
      return f?-x:x;
    }
    inline void work(int x){
      if(z[x]==f[x]){
        s.erase(x);
      }
      else s.insert(x);
    }
    int main(){
      n=rd();
      t1=rd();t2=rd();t3=rd();
      int opt;
      int a,b;////
      u maxx=(1u<<30)-1;
      while(n--){
        opt=rd();
        if(opt==1){
          a=rd();b=rd();
          int wei=maxn-int(b/30);
          int _wei=b%30;
          int tg=0;
          if(a<0)tg=1,a=-a;/////
          for(int j=0;j<30;++j){
              cun[j]=(a&(1u<<j))!=0;
          }
          if(tg)a=-a;
          int now=30-_wei;//
          u num=0;
          for(int j=0;j<now;++j){
              num+=(1u<<j)*cun[j];
          }
          if(a>0){
            num<<=_wei;
            z[wei]=(num+z[wei]);
            num=0;
            if(z[wei]>maxx)
              z[wei]=z[wei]&maxx,num=1;
            for(int j=now;j<30;++j){
              num+=cun[j]*(1u<<j-now);
            }
            --wei;
            z[wei]+=num;
            while(wei>0&&z[wei]>maxx){
              z[wei]&=maxx;
              z[wei-1]++;
              wei--;
            }
          }
          else{
            num<<=_wei;
            f[wei]=(num+f[wei]);
            num=0;
            if(f[wei]>maxx)
              f[wei]=f[wei]&maxx,num=1;
            for(int j=now;j<30;++j){
              num+=cun[j]*(1u<<j-now);
            }
            --wei;
            f[wei]+=num;
            while(wei>0&&f[wei]>maxx){
              f[wei]&=maxx;
              f[wei-1]++;
              wei--;
            }
          }
          int chu=maxn-int(b/30);
          for(int j=wei;j<=chu;++j)work(j);
        }
        else{
          b=rd();
          int wei=maxn-int(b/30);
          int _wei=b%30;
          int ans=(((z[wei]&(1<<_wei))!=0)-((f[wei]&(1<<_wei))!=0)+2)%2;
          bool tag=0;
          for(int j=_wei-1;j>=0;--j)
            if((z[wei]&(1<<j))!=(f[wei]&(1<<j))){
              tag=1;
              if((z[wei]&(1<<j))<(f[wei]&(1<<j)))ans^=1;
              break;
            }
          if(!tag){
            set<int>::iterator it=s.upper_bound(wei);
            if(it!=s.end()){
              int x=*it;
              for(int j=29;j>=0;--j){
                if((z[x]&(1<<j))!=(f[x]&(1<<j))){
                  tag=1;
                  if((z[x]&(1<<j))<(f[x]&(1<<j)))ans^=1;
                  break;
                }
              }
            }
          }
          printf("%d
    ",ans);
        }
      }
      return 0;
    }
    
  • 相关阅读:
    【Vegas原创】更改Linux系统默认语言
    【Vegas原创】RMAN还原一个损坏的user表空间的数据文件
    【Vegas原创】VMWare虚拟的Linux系统下,安装VMWare的增强工具
    【Vegas原创】在线修改redo.log文件的大小
    【Vegas原创】DB和DG的切换
    [工程备案]linux平台,用第三方开源库进行网页抽取和数据解析
    各种流派的正则表达式说明以及shell正则表达式
    python 自然语言处理编码转换
    工作总结2013
    linux上配置boost手记
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/10936257.html
Copyright © 2011-2022 走看看