这是我第一个独立完成的分块题, 恭喜1A!!
题目要你完成两个任务:
- 对区间 [x,y][x,y][x,y] 的所有元素,000 变成 111,111 变成 000
- 查询区间 [x,y][x,y][x,y] 中有多少个 111
很显然就可以用分块做么,(感觉又是套路题)
令 tag[i]tag[i]tag[i] 表示第 iii 个块要变的次数 x % 2x~\% ~2x % 2
但是我们发现这样处理不是很方便,于是我们令设 ans[i]ans[i]ans[i] 表示第 iii 个块目前有多少个元素是 111
对于修改操作 [x,y][x,y][x,y] :
- 对于零散元素,那么我们直接暴力修改 a[i]a[i]a[i] 并更新 ans[i]ans[i]ans[i]
- 对于整块,我们对 tag[i]tag[i]tag[i] 异或 111, 那么 ans[i]ans[i]ans[i] 显然被更新为 len−ans[i]len-ans[i]len−ans[i]
询问也很简单:
- 零散元素答案就是 a[i]a[i]a[i] 异或 tag[i]tag[i]tag[i]
- 整块答案就是 ans[i]ans[i]ans[i]
入门题入门题
int n, m, len, num ;
int a[N], bl[N], l[M], r[M], tag[M], ans[M] ;
void build() {
len = sqrt(n), num = (n - 1) / len + 1 ;
rep(i, 1, n) bl[i] = (i - 1) / len + 1 ;
rep(i, 1, num) l[i] = (i - 1) * len + 1, r[i] = i * len ;
r[num] = n ;
}
void change(int x, int y) {
if (bl[x] == bl[y]) {
rep(i, x, y) {
ans[bl[x]] -= (a[i] ^ tag[bl[x]]) ;
a[i] ^= 1 ;
ans[bl[x]] += (a[i] ^ tag[bl[x]]) ;
}
} else {
rep(i, x, r[bl[x]]) {
ans[bl[x]] -= (a[i] ^ tag[bl[x]]) ;
a[i] ^= 1 ;
ans[bl[x]] += (a[i] ^ tag[bl[x]]) ;
}
rep(i, bl[x] + 1, bl[y] - 1) {
tag[i] ^= 1 ;
ans[i] = len - ans[i] ;
}
rep(i, l[bl[y]], y) {
ans[bl[y]] -= (a[i] ^ tag[bl[y]]) ;
a[i] ^= 1 ;
ans[bl[y]] += (a[i] ^ tag[bl[y]]) ;
}
}
}
int query(int x, int y) {
int s = 0 ;
if (bl[x] == bl[y]) {
rep(i, x, y) s += (a[i] ^ tag[bl[x]]) ;
} else {
rep(i, x, r[bl[x]]) s += (a[i] ^ tag[bl[x]]) ;
rep(i, bl[x] + 1, bl[y] - 1) s += ans[i] ;
rep(i, l[bl[y]], y) s += (a[i] ^ tag[bl[y]]) ;
}
return s ;
}
signed main(){
scanf("%d%d", &n, &m) ;
build() ;
rep(i, 1, m) {
int op, x, y ; scanf("%d%d%d", &op, &x, &y) ;
if (op == 0) change(x, y) ;
else printf("%d\n", query(x, y)) ;
}
return 0 ;
}