• bzoj4742 NOI2017整数


    不会考试题来补一手题解

    题目背景

    在人类智慧的山巅,有着一台字长为10485761048576 位(此数字与解题无关)的超级计算机,著名理论计算机科

    学家P博士正用它进行各种研究。不幸的是,这天台风切断了电力系统,超级计算机

    无法工作,而 P 博士明天就要交实验结果了,只好求助于学过OI的你. . . . . .

    题目描述

    P 博士将他的计算任务抽象为对一个整数的操作。

    具体来说,有一个整数x ,一开始为0 。

    接下来有nn 个操作,每个操作都是以下两种类型中的一种:

    • 1 a b:将x 加上整数a2b ,其中a 为一个整数,b为一个非负整数

    • 2 k :询问x 在用二进制表示时,位权为2^k 的位的值(即这一位上的1 代表 2^k )

    保证在任何时候,x0 。

    输入输出格式

    输入格式:

    输入的第一行包含四个正整数n,t1,t2,t3 ,nn 的含义见题目描述,t1 ,t2 ,t3 的具体含义见子任务。

    接下来n 行,每行给出一个操作,具体格式和含义见题目描述。

    同一行输入的相邻两个元素之间,用恰好一个空格隔开。

    输出格式:

    对于每个询问操作,输出一行,表示该询问的答案(0 或1 )。对于加法操作,没有任何输出。

    说明

    n<=1e6  

    a<=1e9

    b<= 30*n

    考虑一般做法

    建一颗大小为30*n的线段树

    将a的每一位拆开,然后在线段树里找下一个1或0

    复杂度O(30n*log30n)

    看起来很慢

    其实常数够优秀的话是可以A的

    对于非wys选手来说

    其实不需要一位一位的计算

    一个叶子节点记录30位

    将a拆成2个数

    因为进位退位最多为1

    在线段树上面找出一个点以后最长连续一段的0或者(1<<30)-1

    然后就做完了

    复杂度O(nlogn)

    代码不长,挺好写的,就300行左右,也就是一个上午的时间就可以对着大数据调出来啦

    //%std
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<set>
    #include<map>
    using namespace std;
    #define lovelive long long
    #define lc son[x][0]
    #define rc son[x][1]
    #define lowbit(x) (x&(-x))
    #define pt vc
    const int N=1e6+100; 
    void read(int &x)
    {
      int p=1;
      x=0;
      char c=getchar();
      while(c<'0'||c>'9')
      {
        if(c=='-')
          p=-1;
        c=getchar();
      }
      while(c>='0'&&c<='9')
      {
          x=x*10+c-48;
          c=getchar();
      }
      x*=p;
    }
    struct tree{
      int l,r;
      bool sum1,sum0;
      int lazy,key;
    }t[N*4];
    
    void buildtree(int i,int l,int r)
    {
      t[i].l=l;
      t[i].r=r;
      t[i].lazy=-1;
      t[i].sum0=1;
      if(l==r)
        return;
      int mid=(l+r)>>1;
      buildtree(i<<1,l,mid);
      buildtree(i<<1|1,mid+1,r);
    }
    void pushdown(int i)
    {
      if(t[i].lazy==-1)
        return;
      t[i<<1].sum0=t[i<<1|1].sum0=t[i].lazy^1;
      t[i<<1].sum1=t[i<<1|1].sum1=t[i].lazy;
      t[i<<1].lazy=t[i<<1|1].lazy=t[i].lazy;
      if(t[i<<1].l==t[i<<1].r)
        t[i<<1].key=t[i].lazy? (1<<30)-1:0;
      if(t[i<<1|1].l==t[i<<1|1].r)
        t[i<<1|1].key=t[i].lazy? (1<<30)-1:0;
      t[i].lazy=-1;
    }
    
    void change(int i,int pos,int x)
    {
      if(t[i].l>pos||t[i].r<pos)
        return;
      if(t[i].l==t[i].r)
      {
          t[i].sum0=t[i].sum1=0;
          t[i].key=x;
          if(x==((1<<30)-1))
            t[i].sum1=1;
          else
            if(!x)
              t[i].sum0=1;
          return;
      }
      pushdown(i);
      change(i<<1,pos,x);
      change(i<<1|1,pos,x);
      t[i].sum1=t[i<<1].sum1&t[i<<1|1].sum1;
      t[i].sum0=t[i<<1].sum0&t[i<<1|1].sum0;
    }
    void change_(int i,int l,int r,int x)
    {
      if(l>t[i].r||r<t[i].l)
        return;
      if(l<=t[i].l&&t[i].r<=r)
      {
        t[i].sum1=x;
        t[i].sum0=x^1;
        t[i].lazy=x;
        if(t[i].l==t[i].r)
          t[i].key=x? (1<<30)-1:0;
        return;
      }
      pushdown(i);
      change_(i<<1,l,r,x);
      change_(i<<1|1,l,r,x);
      t[i].sum1=t[i<<1].sum1&t[i<<1|1].sum1;
      t[i].sum0=t[i<<1].sum0&t[i<<1|1].sum0;
    }
    
    int find_key(int pos)
    {
      int i=1;
      while(1)
      {
        if(t[i].l==t[i].r)
          return t[i].key;
        pushdown(i);
        if(pos<=t[i<<1].r)
          i=i<<1;
        else
          i=i<<1|1;
      }
     } 
    int find_num1(int pos)
    {
      int i=1,r=1,pre;
      while(t[i].l!=t[i].r)
      {
          pushdown(i);
        if(pos<=t[i<<1].r)
          i=i<<1;
        else
          i=i<<1|1;
      }
      if(!t[i].sum1)
        return 0;
      pre=i;
      i>>=1;
      while(i!=1)
      {
        if(!(pre&1))
        {
          if(!t[pre^1].sum1)
            break;
          else
              r+=t[pre^1].r-t[pre^1].l+1;
        }
        pre=i;
        i>>=1;
      }
      if(pre==(i<<1|1))
        return r;
      i=i<<1|1;
      while(1)
      {
        if(t[i].l==t[i].r)
        {
          r+=t[i].sum1;
          break;
        }
        pushdown(i);
          if(t[i<<1].sum1)
            r+=t[i<<1].r-t[i<<1].l+1,i=i<<1|1;
          else
            i=i<<1;
      }
      return r;
    }
    int find_num0(int pos)
    {
      int i=1,r=1,pre;
      while(t[i].l!=t[i].r)
      {
          pushdown(i); 
        if(pos<=t[i<<1].r)
          i=i<<1;
        else
          i=i<<1|1;
      }
      if(!t[i].sum0)
        return 0;
      pre=i;
      i>>=1;
      while(i!=1)
      {
        if(!(pre&1))
        {
          if(!t[pre^1].sum0)
            break;
          else
              r+=t[pre^1].r-t[pre^1].l+1;
        }
        pre=i;
        i>>=1;
      }
      if(pre==(i<<1|1))
        return r;
      i=i<<1|1;
      while(1)
      {
        if(t[i].l==t[i].r)
        {
          r+=t[i].sum0;
          break;
        }
        pushdown(i);
          if(t[i<<1].sum0)
            r+=t[i<<1].r-t[i<<1].l+1,i=i<<1|1;
          else
            i=i<<1;
      }
      return r;
    }
    void add(int pos,int a)
    {
      int tmp=find_key(pos);
      if(tmp+a<(1<<30))
        change(1,pos,tmp+a);
      else
      {
        change(1,pos,tmp+a-(1<<30));
        tmp=find_num1(pos+1);
        if(tmp)
          change_(1,pos+1,pos+tmp,0);
        change(1,pos+tmp+1,find_key(pos+tmp+1)+1);
      }
    }
    void del(int pos,int a)
    {
      int tmp=find_key(pos);
      if(tmp>=a)
        change(1,pos,tmp-a);
      else
      {
        change(1,pos,tmp-a+(1<<30));
        tmp=find_num0(pos+1);
        if(tmp)
          change_(1,pos+1,pos+tmp,1);
        change(1,pos+tmp+1,find_key(pos+tmp+1)-1);
      }
    }
    int main()
    {
      int n,fk,opt,a,b,x,y,tmp,a1,a2;
    //  freopen("test.in","r",stdin);
    //  freopen("test.out","w",stdout);
      read(n);read(fk);read(fk);read(fk);
      buildtree(1,1,n+1);
      for(int i=1;i<=n;i++)
      {
        if(i==4501)
          i--,i++;
          read(opt);
          if(opt&1)
          {
          read(a);read(b);
          x=b/30+1;
          y=b%30;
          if(a<0)
          {
              a=-a; 
            a1=(a<<y)&((1<<30)-1);
            a2=a>>(30-y);
            del(x,a1);
            if(a2)
              del(x+1,a2);
          }
          else
          {
              a1=(a<<y)&((1<<30)-1);
            a2=a>>(30-y);
            add(x,a1);
            if(a2)
              add(x+1,a2);
          }
        }
        else
        {
          read(a);
          x=a/30+1;
          y=a%30;
          tmp=find_key(x);
          cout<<(tmp>>y&1)<<"
    ";
        }
      }
      return 0;
    }
    /*
    10000 1 1 1
    1 1 30000
    1 1 100
    1 -1 1000
    1 1 10000
    2 10000
    
    10000 1 1 1
    1 1 30000
    1 -1 1000
    1 1 10000
    2 10000
    */
    View Code
  • 相关阅读:
    nodejs REPL清屏
    flask 的relationship使用
    flask 数据库多对多(文章和标签)
    设置管理员的 蘑菇丁日报 周报、月报
    访问个人主页、蘑菇丁、使用:import urllib.request
    使用requests访问、登录蘑菇丁
    UUID
    爬虫经典案例
    selenium 获取 cookies, 然后登录
    用chrome浏览器登录以后 手动找到cookie、加到自己的python代码中
  • 原文地址:https://www.cnblogs.com/NicoDafaGood/p/8856580.html
Copyright © 2020-2023  润新知