传送门
直接把修改的数拆成logloglog个二进制位一个一个修改是会TLETLETLE的。
因此我们把303030个二进制位压成一位储存在线段树里面。
然后维护区间中最靠左二进制位不为0/1的下标。
手动模拟一波进/退位就行了。
代码:
#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
inline int read(){
int ans=0,w=1;
char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans*w;
}
const int N=2e6+5,up=(1<<30)-1,n=1e6;
struct Node{int l,r,val,cov,pos[2];}T[N<<2];
int q,bit[31];
inline void pushup(int p){T[p].pos[0]=min(T[lc].pos[0],T[rc].pos[0]),T[p].pos[1]=min(T[lc].pos[1],T[rc].pos[1]);}
inline void pushnow(int p,int typ){T[p].cov=typ,T[p].val=typ*up,T[p].pos[typ]=n+1,T[p].pos[typ^1]=T[p].l;}
inline void pushdown(int p){if(~T[p].cov)pushnow(lc,T[p].cov),pushnow(rc,T[p].cov),T[p].cov=-1;}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r,T[p].cov=-1;
if(T[p].l==T[p].r){T[p].pos[0]=n+1,T[p].pos[1]=l,T[p].val=0;return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,int v){
if(ql>T[p].r||qr<T[p].l)return;
if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p,v);
pushdown(p);
if(qr<=mid)update(lc,ql,qr,v);
else if(ql>mid)update(rc,ql,qr,v);
else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
pushup(p);
}
inline void modify(int p,int k,int v){
if(T[p].l==T[p].r){T[p].val=v,T[p].pos[0]=T[p].val==0?n+1:T[p].l,T[p].pos[1]=T[p].val==up?n+1:T[p].l;return;}
pushdown(p);
if(k<=mid)modify(lc,k,v);
else modify(rc,k,v);
pushup(p);
}
inline void change(int p,int k,int v){
if(T[p].l==T[p].r){T[p].val+=v,T[p].pos[0]=T[p].val==0?n+1:T[p].l,T[p].pos[1]=T[p].val==up?n+1:T[p].l;return;}
pushdown(p);
if(k<=mid)change(lc,k,v);
else change(rc,k,v);
pushup(p);
}
inline int query(int p,int k){
if(T[p].l==T[p].r)return T[p].val;
pushdown(p);
if(k<=mid)return query(lc,k);
return query(rc,k);
}
inline int ask(int p,int ql,int qr,int typ){
if(ql>T[p].r||qr<T[p].l)return n+1;
if(ql<=T[p].l&&T[p].r<=qr)return T[p].pos[typ];
pushdown(p);
if(qr<=mid)return ask(lc,ql,qr,typ);
if(ql>mid)return ask(rc,ql,qr,typ);
return min(ask(lc,ql,mid,typ),ask(rc,mid+1,qr,typ));
}
int main(){
bit[0]=1;
for(int i=1;i<=30;++i)bit[i]=bit[i-1]<<1;
build(1,1,n);
q=read();
int t=read();
t=read(),t=read();
while(q--){
int op=read();
if(op==1){
long long a=read();
int b=read(),x=b/30+1,y=b%30;
a=a*bit[y];
long long upd=1ll*query(1,x+1)*bit[30]+1ll*query(1,x);
if(a>=0){
upd+=a;
modify(1,x,upd%bit[30]),upd/=bit[30];
modify(1,x+1,upd%bit[30]),upd/=bit[30];
if(!upd)continue;
int id=ask(1,x+2,n,1);
change(1,id,1),update(1,x+2,id-1,0);
}
else{
bool fu=0;
upd+=a;
if(upd<0)upd+=1ll*bit[30]*bit[30],fu=1;
modify(1,x,upd%bit[30]),upd/=bit[30];
modify(1,x+1,upd%bit[30]),upd/=bit[30];
if(!fu)continue;
int id=ask(1,x+2,n,0);
change(1,id,-1),update(1,x+2,id-1,1);
}
}
else{
int a=read(),x=a/30+1,y=a%30;
printf("%d\n",(query(1,x)&bit[y])?1:0);
}
}
return 0;
}