版权声明:thanks for your copy! https://blog.csdn.net/weixin_43907802/article/details/89785337
analysis
首先不难看出来这是一道线段树的题,然后由于这道题要维护的操作和一般的线段树不同,所以考虑修改pushdown函数和lazy标记
考虑修改函数,若将区间中每个数取反,那么其中的1的个数=区间元素个数-原区间1的个数。
此时容易想到让lazy标记代表此区间被XOR情况,1代表被XOR,0代表没有被XOR
由于A^ 1 ^1=A,一段区间如果被XOR两次,就相当于没有被XOR,即lazy标记也要满足XOR原则
自此思路基本完成
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
int n,m;
const int maxn=200010;
int sum[maxn<<2],lazy[maxn<<2];
int a[maxn];
char _A[maxn];
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
inline void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
inline void pushdown(int rt,int l,int r){
if(!lazy[rt])return;
int mid=(l+r)>>1;
lazy[rt<<1]^=1;
lazy[rt<<1|1]^=1;
sum[rt<<1]=mid-l+1-sum[rt<<1];
sum[rt<<1|1]=r-(mid+1)+1-sum[rt<<1|1];
lazy[rt]=0;
}
void buildtree(int l,int r,int rt){
if(l==r){
sum[rt]=a[l];
return;
}
int mid=((l+r)>>1);
buildtree(l,mid,rt<<1);
buildtree(mid+1,r,rt<<1|1);
pushup(rt);
}
int query(int l,int r,int nl,int nr,int rt){
if(l<=nl&&nr<=r)return sum[rt];
pushdown(rt,nl,nr);
int mid=((nl+nr)>>1);
int _sum=0;
if(mid>=l)_sum+=query(l,r,nl,mid,rt<<1);
if(mid<r)_sum+=query(l,r,mid+1,nr,rt<<1|1);
return _sum;
}
void update(int l,int r,int nl,int nr,int rt){
if(l<=nl&&nr<=r){
lazy[rt]^=1;
sum[rt]=(nr-nl+1)-sum[rt];
return;
}
pushdown(rt,nl,nr);
int mid=((nl+nr)>>1);
if(mid>=l)update(l,r,nl,mid,rt<<1);
if(mid<r)update(l,r,mid+1,nr,rt<<1|1);
pushup(rt);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif // ONLINE_JUDGE
clean(sum,0),clean(lazy,0);
read(n),read(m);
scanf("%s",_A);
loop(i,1,n)a[i]=_A[i-1]-'0';
buildtree(1,n,1);
loop(i,1,m){
int _p,_l,_r;read(_p),read(_l),read(_r);
if(_p==0)update(_l,_r,1,n,1);
else if(_p==1)printf("%d\n",query(_l,_r,1,n,1));
}
return 0;
}
anayisis
就是上面那道题嘛!代码都不用咋改(luogu上有3道和这个一模一样的题)
code
#include<bits/stdc++.h>
using namespace std;
#define loop(i,start,end) for(register int i=start;i<=end;++i)
#define clean(arry,num) memset(arry,num,sizeof(arry))
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a<b)?a:b)
int n,m;
const int maxn=200010;
int sum[maxn<<2],lazy[maxn<<2];
int a[maxn];
char _A[maxn];
template<typename T>void read(T &x){
x=0;char r=getchar();T neg=1;
while(r>'9'||r<'0'){if(r=='-')neg=-1;r=getchar();}
while(r>='0'&&r<='9'){x=(x<<1)+(x<<3)+r-'0';r=getchar();}
x*=neg;
}
inline void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
inline void pushdown(int rt,int l,int r){
if(!lazy[rt])return;
int mid=(l+r)>>1;
lazy[rt<<1]^=1;
lazy[rt<<1|1]^=1;
sum[rt<<1]=mid-l+1-sum[rt<<1];
sum[rt<<1|1]=r-(mid+1)+1-sum[rt<<1|1];
lazy[rt]=0;
}
void buildtree(int l,int r,int rt){
if(l==r){
sum[rt]=a[l];
return;
}
int mid=((l+r)>>1);
buildtree(l,mid,rt<<1);
buildtree(mid+1,r,rt<<1|1);
pushup(rt);
}
int query(int l,int r,int nl,int nr,int rt){
if(l<=nl&&nr<=r)return sum[rt];
pushdown(rt,nl,nr);
int mid=((nl+nr)>>1);
int _sum=0;
if(mid>=l)_sum+=query(l,r,nl,mid,rt<<1);
if(mid<r)_sum+=query(l,r,mid+1,nr,rt<<1|1);
return _sum;
}
void update(int l,int r,int nl,int nr,int rt){
if(l<=nl&&nr<=r){
lazy[rt]^=1;
sum[rt]=(nr-nl+1)-sum[rt];
return;
}
pushdown(rt,nl,nr);
int mid=((nl+nr)>>1);
if(mid>=l)update(l,r,nl,mid,rt<<1);
if(mid<r)update(l,r,mid+1,nr,rt<<1|1);
pushup(rt);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("datain.txt","r",stdin);
#endif // ONLINE_JUDGE
clean(sum,0),clean(lazy,0);
read(n),read(m);
loop(i,1,m){
int _p,_l,_r;read(_p),read(_l),read(_r);
if(_p==0)update(_l,_r,1,n,1);
else if(_p==1)printf("%d\n",query(_l,_r,1,n,1));
}
return 0;
}
*