F: 操作数
题意:
有n个数初始时都是0,m次操作,
共有两种操作,
1.输入L和R将[L,R]区间内的数反转,将1变成0,0变成1
2.输入X,查询第x个数是0还是1
题解:
一道线段树的题,根据题意,因为每个数初始化为0,所以可以不用建树这个操作,只需要一个懒惰标记数组就可以了,对于每次反转,只需将这个区间标记一次,然后对于每次查询,只需判断每个数被标记过几次,当被标记的此时为偶数时,则x为0,若为奇数则为1。
#include<iostream>
#include<cstdio>
//#defien M 100005
const int M=100005;
using namespace std;
int Sum[4*M],Add[4*M];
void PushDown(int rt)//懒惰标记,向下传递
{
if(Add[rt])
{
Add[rt*2]+=Add[rt];
Add[rt*2+1]+=Add[rt];
Add[rt]=0;
}
}
void UpDate(int L,int R,int l,int r,int rt)//区间修改
{
if(L<=l && r<=R)
{
Add[rt]+=1;
return ;
}
PushDown(rt);
int m=(l+r)/2;
if(L<=m) UpDate(L,R,l,m,rt*2);
if(m<R) UpDate(L,R,m+1,r,rt*2+1);
}
int Query(int p,int l,int r,int rt)
{
if(l==r)
return Add[rt];
PushDown(rt);
int m=(l+r)/2;
if(p<=m)
Query(p,l,m,rt*2);
else
Query(p,m+1,r,rt*2+1);
}
int main()
{
int n,m;scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
int x;scanf("%d",&x);
if(x==1)
{
int l,r;
scanf("%d %d",&l,&r);
UpDate(l,r,1,n,1);
}
if(x==2)
{
int i;
scanf("%d",&i);
printf("%d\n",Query(i,1,n,1)%2);
}
}
return 0;
}