把数转换成二进制维护
那么进位就是把之后一段连续1变成0,后面的0变成1
退位就是把之后一段连续的0变成1,后面的1变成0
这样可以用线段树维护
有一个 nlog2n 的暴力,就是把这个数的每一个为1的位取出来,用线段树加进去,a为负的同理
如果把原来的01序列压位一下(我压了30位),那么a最多跨2个30位整数,把这两位取出来,拼成一个60位整数,然后把加上去,因为最多进(退)一位,按上面的方法维护就可以了
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=2e6+10,base=30,MAX=2e6,ALL1=(1LL< 1,ALL0=0;
const ll inf=1LL<<60;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(),f=1; x=0;
for(;c>'9'||c<'0';(f=c=='-'?-f:f),c=nc());for(;c>='0'&&c<='9';x=x*10+f*(c-'0'),c=nc());
}
int n,t,type,a,b,k;
bool a0[N<<2],a1[N<<2];
int num[N<<2],tag[N<<2];
int fir0[1<<16],fir1[1<<16];
inline void Up(int g){
a0[g]=a0[g<<1] && a0[g<<1|1];
a1[g]=a1[g<<1] && a1[g<<1|1];
}
inline void set0(int g){ num[g]=ALL0; tag[g]=0; a0[g]=1; a1[g]=0; }
inline void set1(int g){ num[g]=ALL1; tag[g]=1; a1[g]=1; a0[g]=0; }
inline void Push(int g){
if(~tag[g])
if(tag[g]) set1(g<<1),set1(g<<1|1);
else set0(g<<1),set0(g<<1|1);
tag[g]=-1;
}
int Query(int g,int x,int L,int R){
if(L==R) return num[g];
int mid=L+R>>1; Push(g);
if(x<=mid) return Query(g<<1,x,L,mid);
else return Query(g<<1|1,x,mid+1,R);
}
int Find0(int g,int l,int r,int L,int R){
if(L==R) return num[g]!=ALL1?L:-1;
int mid=L+R>>1; Push(g);
if(l==L&&r==R){
if(!a1[g<<1]) return Find0(g<<1,l,mid,L,mid);
return Find0(g<<1|1,mid+1,r,mid+1,R);
}
if(r<=mid) return Find0(g<<1,l,r,L,mid);
if(l>mid) return Find0(g<<1|1,l,r,mid+1,R);
int ret=Find0(g<<1,l,mid,L,mid);
if(~ret) return ret;
return Find0(g<<1|1,mid+1,r,mid+1,R);
}
int Find1(int g,int l,int r,int L,int R){
if(L==R) return num[g]!=ALL0?L:-1;
int mid=L+R>>1; Push(g);
if(l==L&&r==R){
if(!a0[g<<1]) return Find1(g<<1,l,mid,L,mid);
return Find1(g<<1|1,mid+1,r,mid+1,R);
}
if(r<=mid) return Find1(g<<1,l,r,L,mid);
if(l>mid) return Find1(g<<1|1,l,r,mid+1,R);
int ret=Find1(g<<1,l,mid,L,mid);
if(~ret) return ret;
return Find1(g<<1|1,mid+1,r,mid+1,R);
}
void Modify(int g,int x,int y,int L,int R){
if(L==R){
num[g]=y; a0[g]=y==ALL0; a1[g]=y==ALL1;
return ;
}
int mid=L+R>>1; Push(g);
if(x<=mid) Modify(g<<1,x,y,L,mid);
else Modify(g<<1|1,x,y,mid+1,R);
Up(g);
}
void Cover0(int g,int l,int r,int L,int R){
if(l==L&&r==R) return set0(g),void("%%%%gjghfd%%%%");
int mid=L+R>>1; Push(g);
if(r<=mid) Cover0(g<<1,l,r,L,mid);
else if(l>mid) Cover0(g<<1|1,l,r,mid+1,R);
else Cover0(g<<1,l,mid,L,mid),Cover0(g<<1|1,mid+1,r,mid+1,R);
Up(g);
}
void Cover1(int g,int l,int r,int L,int R){
if(l==L&&r==R) return set1(g),void("%%%%gjghfd%%%%");
int mid=L+R>>1; Push(g);
if(r<=mid) Cover1(g<<1,l,r,L,mid);
else if(l>mid) Cover1(g<<1|1,l,r,mid+1,R);
else Cover1(g<<1,l,mid,L,mid),Cover1(g<<1|1,mid+1,r,mid+1,R);
Up(g);
}
inline void Out(){
return ;
puts("-----");
//for(int i=1;i<=20;i++)
// printf("%d ",Query(1,i,1,MAX));
printf("%d ",Query(1,46488,1,MAX));
puts("\n-----");
}
int main(){
rea(n); rea(t); rea(t); rea(t);
memset(a0,1,sizeof(a0)); memset(tag,-1,sizeof(tag));
fir0[1]=1; fir1[1]=0; fir1[0]=15;
for(int i=2;i<1<<15;i++)
fir0[i]=i&1?fir0[i>>1]+1:0,fir1[i]=i&1?0:fir1[i>>1]+1;
while(n--){
rea(type);
if(type&1){
rea(a); rea(b);
if(a>0){
int pos=b/base+1; ll cur=((ll)a<<(b%base))+((ll)Query(1,pos+1,1,MAX)< 1,pos,1,MAX);
if(cur>=inf){
cur-=inf;
int p=Find0(1,pos+2,MAX,1,MAX),q=Query(1,p,1,MAX);
if(pos+21,pos+2,p-1,1,MAX);
int w=fir0[q&32767]<15?fir0[q&32767]:fir0[q>>15]+15;
q^=(1<1)-1;
Modify(1,p,q,1,MAX);
}
Modify(1,pos+1,cur>>base,1,MAX); Modify(1,pos,cur&ALL1,1,MAX);
}
else{
a=-a;
int pos=b/base+1; ll cur=((ll)Query(1,pos+1,1,MAX)< 1,pos,1,MAX)-((ll)a<<(b%base));
if(cur<0){
cur+=inf;
int p=Find1(1,pos+2,MAX,1,MAX),q=Query(1,p,1,MAX);
if(pos+21,pos+2,p-1,1,MAX);
int w=fir1[q&32767]<15?fir1[q&32767]:fir1[q>>15]+15;
q^=(1<1)-1;
Modify(1,p,q,1,MAX);
}
Modify(1,pos+1,cur>>base,1,MAX); Modify(1,pos,cur&ALL1,1,MAX);
}
}
else{
rea(k);
int pos=k/base+1,Q=Query(1,pos,1,MAX); k%=base;
if(Q>>k&1) puts("1"); else puts("0");
}
Out();
}
return 0;
}