Build后忘push_up简直有毒
【题目分析】
题意还是很明显的,支持区间取反,区间查询。
所以我们线段树的sum数组开成二维的,第一维记录关的灯的数量,第二维记录开着的灯的数量。
push_down的lazy标记就swap一下0和1的个数。
查询时返回区间1的sum即可。
【代码~】
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;
int laz[MAXN<<2];
int zt[MAXN<<2],sum[MAXN<<2][2];
int n,q;
void push_up(int root)
{
sum[root][0]=sum[root<<1][0]+sum[root<<1|1][0];
sum[root][1]=sum[root<<1][1]+sum[root<<1|1][1];
}
void push_down(int root)
{
if(laz[root])
{
swap(sum[root<<1][0],sum[root<<1][1]);
swap(sum[root<<1|1][0],sum[root<<1|1][1]);
laz[root<<1]^=1;
laz[root<<1|1]^=1;
laz[root]=0;
}
}
void build(int root,int l,int r)
{
if(l==r)
{
sum[root][0]=1;
return ;
}
int mid=l+r>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
push_up(root);
}
void update(int root,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
laz[root]^=1;
swap(sum[root][0],sum[root][1]);
return ;
}
push_down(root);
int mid=l+r>>1;
if(L<=mid)
update(root<<1,l,mid,L,R);
if(R>mid)
update(root<<1|1,mid+1,r,L,R);
push_up(root);
}
int query(int root,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
return sum[root][1];
int ret=0,mid=l+r>>1;
push_down(root);
if(L<=mid)
ret+=query(root<<1,l,mid,L,R);
if(R>mid)
ret+=query(root<<1|1,mid+1,r,L,R);
return ret;
}
int main()
{
scanf("%d%d",&n,&q);
build(1,1,n);
while(q--)
{
int cz,l,r;
scanf("%d%d%d",&cz,&l,&r);
if(cz==0)
update(1,1,n,l,r);
else
printf("%d\n",query(1,1,n,l,r));
}
return 0;
}