[TJOI2009] 开关
线段树其实就行了
试一下分块
但很奇怪TLE了
调到200才A
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
#define MAXN 150005
int N,M;
struct BLOCK {
int drop[MAXN],sum[MAXN],num[MAXN],block;
inline void init() {
block = sqrt(N)>200?200:sqrt(N);
for(int i=0;i<N;++i) drop[i] = sum[i] = 0;
}
inline void reset(int k) {
sum[k] = 0;
for(int i=k*block;i<=min(N-1,block*(k+1)-1);++i) {
drop[i] = (num[k]&1)?(drop[i]^1):drop[i];
if(drop[i]) sum[k] ++;
}
num[k] = 0;
}
inline void update(int l,int r) {
l--; r--;
reset(l/block);
for(;l<=r&&l%block;++l) {
drop[l] ^= 1;
if(drop[l]) sum[l/block] ++;
else sum[l/block] --;
}
for(;l+block-1<=r;l+=block) {
num[l/block] ++; sum[l/block] = block - sum[l/block];
}
if(l<=r) reset(r/block);
for(;l<=r;++l) {
drop[l] ^= 1;
if(drop[l]) sum[l/block] ++;
else sum[l/block] --;
}
}
inline int query(int l,int r) {
l--; r--;
int ans = 0; reset(l/block);
for(;l<=r&&l%block;++l)
if(drop[l]) ans ++;
for(;l+block-1<=r;l+=block)
ans += sum[l/block];
if(l<=r) reset(r/block);
for(;l<=r;++l)
if(drop[l]) ans ++;
return ans;
}
} B;
int main() {
cin >> N >> M; B.init();
for(int i=1;i<=M;++i) {
int opt ,l,r;
cin >> opt >> l >> r;
if(opt==0) B.update(l,r);
else cout << B.query(l,r) << "\n";
}
}