和题解思路差不多,用unsigned int压位,维护加的值和减的值
加的时候暴力加,通过判断溢出来判断进位;询问的时候用set判断当前unsigned int之后第一个加减标记不等的位置,先把要询问的位置异或,然后通过判断后缀大小来判断是否借位,即若减后缀大就借位(把ans取反)。
只过了16分 ,蒟蒻求助
代码:
#include <cstdio>
#include <cctype>
#include <cstring>
#include <set>
#include <algorithm>
#define R register int
using std::set;
namespace quick {
//毒瘤快读
}
using namespace quick;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
const int maxn=1e6+20,inf=0x3f3f3f3f;
int n,t[4];
uint posn[maxn],nagn[maxn];
set<uint , std::greater<uint> > s;//有序储存正负不相等的32位
inline void plus(uint a,uint b,uint *f) {
register uint k(b/32),old;
b%=32;
while(a) {
old=f[k];
f[k]+=a<<b;
a>>=1;
a>>=(31-b);
if(f[k]<old) a++;
if(posn[k]!=nagn[k]) s.insert(k);
else s.erase(k);
b=0;k++;
}
}
inline uint query(uint a) {
register uint k(a/32);
a%=32;
uint ans=((posn[k]^nagn[k])>>a)&1;
set<uint , std::greater <uint> >::iterator it=s.lower_bound(k);
if(it==s.end()) return ans;
uint p=*it;
if(!a&&p==k) {
++it;
if(it==s.end()) return ans;
p=*it;
}
if(p<k&&posn[p]<nagn[p]) ans^=1;
else {
uint x=posn[k]&((1<<a)-1),y=nagn[k]&((1<<a)-1);
if(x<y) ans^=1;
}
return ans;
}
int main(void) {
#ifndef ONLINE_JUDGE
freopen("int.in","r",stdin);
#endif
read(n,t[1],t[2],t[3]);
for(R i(1);i<=n;i++) {
R opt,a,b;
read(opt);
if(opt==1) {
read(a,b);
if(!a) continue;
if(a>0) plus(a,b,posn);
else plus(-a,b,nagn);
}
else if(opt==2) {
read(a);
write(query(a),'\n');
}
}
flush();
return 0;
}