区间修改就可以使用线段树来进行维护
而且鉴于xor的特性
0 xor 1 = 1
1 xor 1 =0
所以在处理懒标记的时候就可使1的个数和0的个数互换就可以了
也可以使用做差的方法
因为1/0 xor 1 就相当于减1.
上code
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
char base[300000];
struct node
{
int num_1;
int num_0;
int tag;
};
node t[1000000];
void merge(int root)
{
t[root].num_1=t[root<<1].num_1+t[root<<1|1].num_1;
t[root].num_0=t[root<<1].num_0+t[root<<1|1].num_0;
return ;
}
void push_down(int root)
{
if(t[root].tag)
{
t[root].tag=0;
t[root<<1].tag^=1;
t[root<<1|1].tag^=1;
swap(t[root<<1].num_0,t[root<<1].num_1);
swap(t[root<<1|1].num_0,t[root<<1|1].num_1);
}
return ;
}
void build(int root,int l,int r)
{
if(l==r)
{
t[root].num_0=(base[l]=='0' ? 1 : 0);
t[root].num_1=(base[l]=='1' ? 1 : 0);
t[root].tag=0;
return ;
}
int mid=(l+r)>>1;
build(root<<1,l,mid);
build(root<<1|1,mid+1,r);
merge(root);
return ;
}
void change(int root,int nl,int nr,int al,int ar)
{
if(nl>ar||nr<al)
return ;
if(nl>=al&&nr<=ar)
{
swap(t[root].num_0,t[root].num_1);
t[root].tag^=1;
return ;
}
push_down(root);
int mid=(nl+nr)>>1;
change(root<<1,nl,mid,al,ar);
change(root<<1|1,mid+1,nr,al,ar);
merge(root);
return ;
}
int check(int root,int nl,int nr,int al,int ar)
{
if(nl>ar||nr<al)
return 0;
if(nl>=al&&nr<=ar)
return t[root].num_1;
int mid=(nl+nr)>>1;
push_down(root);
int res=check(root<<1,nl,mid,al,ar)+
check(root<<1|1,mid+1,nr,al,ar);
merge(root);
return res;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",base+1);
int len=n;
build(1,1,len);
int a,b,c;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(!a)
change(1,1,len,b,c);
else
printf("%d
",check(1,1,len,b,c));
}
return 0;
}
打模板的速度还是挺快的。
不跟有些人一样,拿着打模板说事。