luogu P3822 [NOI2017] 整数
题面传送门
本来想写个\(O(n\log n\log a)\)的暴力没想到过了
考虑二进制加法的本质是啥。
其实就是把前面一堆连续的\(1\)变成\(0\),然后把第一个\(0\)变成\(1\)即可。
然后把\(a\)按照二进制位拆开写个平衡树就可以\(O(n\log n\log W)\)啦!
但是这样实在是太逊了。
考虑如果\(a>0\),想到算导上提到过只加的情况下二进制加法进位是总共\(O(n)\)的。
但是有\(a<0\),那么就可以分开来维护,维护两个大数,一个表示加了多少,一个表示减了多少。
但是计算哪一位是什么的时候如果直接将这一位相减就是错的,因为有借位。
那么就可以找到后面最近的一个不同的位置是啥,然后判断是不是要进位即可。
然后你发现这个东西还是\(O(n\log n\log a)\)的
但是复杂度均摊!跑不满!于是就过了。
实际上还要\(32\)位一段分块然后对块整体维护。可以把复杂度除掉\(30\)但是我懒得写
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 1001000
#define M N*N+5
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
using namespace std;
int n,op,a,b,T1,T2,T3;bitset<N*30+5>A,B;set<int> F;set<int>::it pus;
I void CG(int x){A[x]^B[x]?(F.erase(x),0):(F.insert(x),0);}
I void Ina(int x){while(A[x]) CG(x),A[x++]=0;CG(x);A[x]=1;}
I void Inb(int x){while(B[x]) CG(x),B[x++]=0;CG(x);B[x]=1;}
struct IO{
static const int S=1<<21;
char buf[S],*p1,*p2;int st[105],Top;
~IO(){clear();}
inline void clear(){fwrite(buf,1,Top,stdout);Top=0;}
inline void pc(const char c){Top==S&&(clear(),0);buf[Top++]=c;}
inline char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
inline IO&operator >> (char&x){while(x=gc(),x==' '||x=='\n'||x=='\r');return *this;}
template<typename T>inline IO&operator >> (T&x){
x=0;bool f=0;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-') f^=1;ch=gc();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=gc();
f?x=-x:0;return *this;
}
inline IO&operator << (const char c){pc(c);return *this;}
template<typename T>inline IO&operator << (T x){
if(x<0) pc('-'),x=-x;
do{st[++st[0]]=x%10,x/=10;}while(x);
while(st[0]) pc('0'+st[st[0]--]);return *this;
}
}fin,fout;
int main(){
// freopen("1.in","r",stdin);
RI i;scanf("%d%d%d%d",&n,&T1,&T2,&T3);while(n--){
fin>>op;if(op==1){
fin>>a>>b;if(a>0) for(i=0;i<=30;i++) a>>i&1&&(Ina(b+i),0);
else for(a=-a,i=0;i<=30;i++) a>>i&1&&(Inb(b+i),0);
}else {fin>>a;b=A[a]-B[a]; pus=F.lower_bound(a);pus!=F.begin()&&(b-=(!A[*--pus]));cout<<(b+2)%2<<'\n';}
}
}