• [bzoj4942]整数


    考虑暴力,即需要考虑如何实现$pm 2^{k}$,相当于要找到之后的第一个0或者之前的第一个1(维护区间是否全0/1即可),然后区间重置,可以用线段树维护,复杂度为$o(900n)$(a的划分和线段树),无法通过
    但由于数据范围很大,这样过不了,可以想到压位,每30位二进制压为一个数,那么复杂度降为$o(30n)$(因为a只要划分为最多两个数)且常数变小,可以通过

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 1000100
      4 #define L (k<<1)
      5 #define R (L+1)
      6 #define mid (l+r>>1)
      7 #define S (1<<30)
      8 int n,p,x,y,f[N],laz[N<<2],pos[N<<2],vis[N<<2][2];
      9 int pd(int k){
     10     if (!k)return 0;
     11     if (k==S-1)return 1;
     12     return -1;
     13 }
     14 void build(int k,int l,int r){
     15     laz[k]=-1;
     16     vis[k][0]=1;
     17     if (l==r){
     18         pos[k]=l;
     19         return;
     20     }
     21     build(L,l,mid);
     22     build(R,mid+1,r);
     23 }
     24 void upd(int k,int x){
     25     laz[k]=x;
     26     if (x<0){
     27         vis[k][0]=vis[k][1]=0;
     28         return;
     29     }
     30     if (pos[k])f[pos[k]]=x*(S-1);
     31     vis[k][x]=1;
     32     vis[k][x^1]=0;
     33 }
     34 void up(int k){
     35     vis[k][0]=(vis[L][0]&vis[R][0]);
     36     vis[k][1]=(vis[L][1]&vis[R][1]);
     37 }
     38 void down(int k){
     39     if (laz[k]<0)return;
     40     upd(L,laz[k]);
     41     upd(R,laz[k]);
     42     laz[k]=-1;
     43 }
     44 void update(int k,int l,int r,int x,int y,int z){
     45     if ((l>y)||(x>r))return;
     46     if ((x<=l)&&(r<=y)){
     47         upd(k,z);
     48         return;
     49     }
     50     down(k);
     51     update(L,l,mid,x,y,z);
     52     update(R,mid+1,r,x,y,z);
     53     up(k);
     54 }
     55 int find(int k,int l,int r,int x,int y){
     56     if ((r<=x)||(vis[k][y]))return 0;
     57     if (l==r)return l;
     58     down(k);
     59     int p=find(L,l,mid,x,y);
     60     if (p)return p;
     61     return find(R,mid+1,r,x,y);
     62 }
     63 int query(int k,int l,int r,int x){
     64     if (l==r)return f[l];
     65     down(k);
     66     if (x<=mid)return query(L,l,mid,x);
     67     return query(R,mid+1,r,x);
     68 }
     69 void add(int x,int y){
     70     if (query(1,1,N,x)+y<S){
     71         update(1,1,N,x,x,pd(f[x]+=y));
     72         return;
     73     }
     74     update(1,1,N,x,x,pd(f[x]+=y-S));
     75     int p=find(1,1,N,x,1);
     76     update(1,1,N,x+1,p-1,0);
     77     query(1,1,N,p);
     78     update(1,1,N,p,p,pd(++f[p]));
     79 }
     80 void del(int x,int y){
     81     if (query(1,1,N,x)>=y){
     82         update(1,1,N,x,x,pd(f[x]-=y));
     83         return;
     84     }
     85     update(1,1,N,x,x,pd(f[x]+=S-y));
     86     int p=find(1,1,N,x,0);
     87     update(1,1,N,x+1,p-1,1);
     88     query(1,1,N,p);
     89     update(1,1,N,p,p,pd(--f[p]));
     90 }
     91 int main(){
     92     scanf("%d%*d%*d%*d",&n);
     93     build(1,1,N);
     94     while (n--){
     95         scanf("%d%d",&p,&x);
     96         if (p==2)printf("%d
    ",(query(1,1,N,x/30+1)>>(x%30))&1);
     97         else{
     98             scanf("%d",&y);
     99             if (x>0){
    100                 add(y/30+1,(x*(1LL<<(y%30))%S));
    101                 add(y/30+2,(x*(1LL<<(y%30))/S));
    102             }
    103             else{
    104                 x*=-1;
    105                 del(y/30+1,(x*(1LL<<(y%30))%S));
    106                 del(y/30+2,(x*(1LL<<(y%30))/S));
    107             }
    108         }
    109     }
    110 } 
    View Code
  • 相关阅读:
    线段树优化dp(elect选择)
    gdb调试
    无参装饰器
    3.23作业
    3.22周末作业
    函数对象与闭包函数
    3.20作业
    3.19作业
    名称空间与作用域
    函数参数的使用
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11935790.html
Copyright © 2020-2023  润新知