#include <bits/stdc++.h>
using namespace std;
using VI = vector<int>;
using ll = long long;
using PII = pair<int,int>;
const int mod = 19650827;
int n,q;
int a[200010];
struct g{
int val,left,right;
int add;
}t[500050];
void build(int p,int l,int r){
t[p].left = l,t[p].right = r;
if(l == r){
t[p].val = 0;
return;
}
int mid = (l + r) >> 1;
build(2*p,l,mid);
build(2*p+1,mid+1,r);
t[p].val = t[2*p].val + t[2*p+1].val;
}
void spread(int p){
if(t[p].add == 0) return;
t[2*p].val = (t[2*p].right - t[2*p].left + 1) - t[2*p].val;
t[2*p+1].val = (t[2*p+1].right - t[2*p+1].left + 1) - t[2*p+1].val;
t[2*p].add ^= 1;
t[2*p+1].add ^= 1;
t[p].add = 0;
}
void change(int p,int l,int r){
if(l <= t[p].left && r >= t[p].right){
t[p].val = (t[p].right - t[p].left + 1) - t[p].val;
t[p].add ^= 1;
return;
}
spread(p);
int mid = (t[p].left + t[p].right) >> 1;
if(l <= mid) change(2*p,l,r);
if(r > mid) change(2*p+1,l,r);
t[p].val = t[2*p].val + t[2*p+1].val;
}
int ask(int p,int l,int r){
if(l <= t[p].left && r >= t[p].right){
return t[p].val;
}
spread(p);
int res = 0;
int mid = (t[p].left + t[p].right) >> 1;
if(l <= mid) res += ask(2*p, l , r);
if(r > mid) res += ask(2*p+1, l , r);
return res;
}
int main(){
cin>>n>>q;
build(1,1,n);
while(q--){
int c,a,b;
scanf("%d%d%d",&c,&a,&b);
if(c == 0){
change(1,a,b);
//cout<<t[1].val<<"\n";
}else{
printf("%d\n", ask(1,a,b));
}
}
}
虽然是个线段树板子题,但也让我对线段树有了点理解
其实关键在于lazy标记 通过这个实现每次查询的时候再修改
spread以后记得把懒标记清除