考虑暴力,即需要考虑如何实现$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 }