为什么这玩意是双tag呢
因为他按理来说正解是用线段树来做的,但是有很多题解都是直接上set搞的,所以就两个tag都打上了
首先我们可以想到用bitset来表示这个整数,然后我们就会发现所谓的修改直接暴力改就完事
然后正负分开记录,询问的时候在加起来
若当前位相同,后缀非负则答案为 0,否则为 1。
若当前位不同,后缀非负则答案为 1,否则为 0。
我们会发现它大部分时候其实都是相同的,我们可以用set记录正负数组不同的位置。
#include<bits/stdc++.h>
#define for1(i,a,b) for(int i = a;i<=b;i++)
#define ll long long
#define mp(a,b) make_pair(a,b)
using namespace std;
set<int>s;
set <int>::iterator ji;
bitset<30005005>aa,bb;
void rua(int x,int v)
{
int zz=v,l=v+1,r=0;
while(x)
{
int ad=(x&1);
zz++;
if(ad)
if(aa[zz])
{
aa.set(zz,0);
x++;
}
else aa.set(zz,1);
x>>=1;
}
r=zz;
for1(i,l,r)
{
if(aa[i]^bb[i])
s.insert(i);
else s.erase(i);
}
}
void rub(int x,int v)
{
int zz=v,l=v+1,r=0;
while(x)
{
int ad=(x&1);
zz++;
if(ad)
if(bb[zz])
{
bb.set(zz,0);
x++;
}
else bb.set(zz,1);
x>>=1;
}
r=zz;
for1(i,l,r)
{
if(aa[i]^bb[i])
s.insert(i);
else
s.erase(i);
}
}
void add(int x,int v)
{
if(x>0)
rua(x,v);
else
rub(-x,v);
return ;
}
void ask(int x)
{
int pd1,pd2;
ji=s.lower_bound(x);
ji--;
pd1=(aa[x]^bb[x])? 1:0;
pd2=(aa[*ji]<bb[*ji])? 1:0;
if(pd1^pd2)
puts("1");
else
puts("0");
}
int main()
{
int n,t,a,b;
cin>>n>>t>>t>>t;
s.insert(0);
s.insert(30*n+50);
for1(i,1,n)
{
scanf("%d%d",&t,&a);
if(t==1)
{
scanf("%d",&b);
add(a,b);
}
else
ask(++a);
}
}
标签:aa,10,set,bb,17,int,else,NOI2017,zz
From: https://www.cnblogs.com/yyx525jia/p/16799831.html