#include <bits/stdc++.h>
using namespace std;
int len, n, a[100005], b[100005], m;
int id[100005], sum[100005];
void change(int l, int r) {
if (id[l] == id[r]) {
for (int i = l; i <= r; i++) {
a[i] = (a[i] + 1) % 2; //0或1加1再对2取膜等价于反转
sum[id[i]] += (a[i] == 1 ? 1 : -1); //a[i]为一说明原来是0, 加了1, 为0则相反
}
}
else {
for (int i = l; id[i] == id[l]; i++) {
a[i] = (a[i] + 1) % 2;
sum[id[i]] += (a[i] == 1 ? 1 : -1);
//左半块反转
}
for (int i = id[l] + 1; i < id[r]; i++) {
b[i] = (b[i] + 1) %2; //加2相当于没变, 加3相当于加1, 所以块被加和也膜2
sum[i] += len - sum[i]; //块和反转, 如10010, 反转后为01101, 原有2个, 现有3个, 可见块和反转直接用块长-原块和
}
for (int i = r; id[i] == id[r]; i--) {
a[i] = (a[i] + 1) %2;
sum[id[i]] += (a[i] == 1 ? 1 : -1);
//右半块反转
}
}
return ;
}
int query(int l, int r) {
int ans = 0;
if (id[l] == id[r]) {
for (int i = l; i <= r; i++) {
ans += (a[i] + b[id[i]]) % 2; //计算i点是否打开
}
}
else {
for (int i = l; id[i] == id[l]; i++)
ans += (a[i] + b[id[i]]) %2;
//左半块相加
for (int i = id[l] + 1; i < id[r]; i++)
ans += sum[i]; //块和已经处理好了, 直接加上
for (int i = r; id[i] == id[r]; i--)
ans += (a[i] + b[id[i]]) % 2;
//右半块相加
}
return ans;
}
int main() {
cin >> n >> m;
len = sqrt(n); //求块长
for (int i = 1; i <= n; i++)
id[i] = i / len + 1; //分块
for (int i = 1, k, l, r; i <= m; i++) {
cin >> k >> l >> r;
switch(k) {
case 0:
change(l, r); //区间反转
break;
case 1:
cout << query(l, r) << endl; //区间查询
break;
}
}
return 0;
}
样例已过
A1 WA9