[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\n",(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

猜你喜欢

转载自www.cnblogs.com/PYWBKTDA/p/11935790.html
今日推荐