题目描述
现有 nnn 盏灯排成一排,从左到右依次编号为:111,222,……,nnn。然后依次执行 mmm 项操作。
操作分为两种:
- 指定一个区间 [a,b][a,b][a,b],然后改变编号在这个区间内的灯的状态(把开着的灯关上,关着的灯打开);
- 指定一个区间 [a,b][a,b][a,b],要求你输出这个区间内有多少盏灯是打开的。
灯在初始时都是关着的。
输入格式
第一行有两个整数 nnn 和 mmm,分别表示灯的数目和操作的数目。
接下来有 mmm 行,每行有三个整数,依次为:ccc、aaa、bbb。其中 ccc 表示操作的种类。
- 当 ccc 的值为 000 时,表示是第一种操作。
- 当 ccc 的值为 111 时,表示是第二种操作。
aaa 和 bbb 则分别表示了操作区间的左右边界。
输出格式
每当遇到第二种操作时,输出一行,包含一个整数,表示此时在查询的区间中打开的灯的数目。
输入输出样例 #1
输入 #1
4 5
0 1 2
0 2 4
1 2 3
0 2 4
1 1 4
输出 #1
1
2
说明/提示
数据规模与约定
对于全部的测试点,保证 2≤n≤1052\le n\le 10^52≤n≤105,1≤m≤1051\le m\le 10^51≤m≤105,1≤a,b≤n1\le a,b\le n1≤a,b≤n,c∈{0,1}c\in\{0,1\}c∈{0,1}。
solution
用线段树维护开关灯信息
代码
#include <sstream>
#include "iostream"
#include "cmath"
#include "vector"
#include "algorithm"
using namespace std;
const int N = 1e5 + 5;
int n;
struct node {
int sum, tag;
} a[4 * N];
// 将父节点的 tag 信息向下分摊
void push_down(int rt, int l, int r) {
if (a[rt].tag) {
int m = r + l >> 1;
a[rt * 2].sum = m - l + 1 - a[rt * 2].sum;
a[rt * 2].tag = 1 - a[rt * 2].tag;
a[rt * 2 + 1].sum = r - m - a[rt * 2 + 1].sum;
a[rt * 2 + 1].tag = 1 - a[rt * 2 + 1].tag;
a[rt].tag = 0;
}
}
void push_up(int rt) {
a[rt].sum = a[rt * 2].sum + a[rt * 2 + 1].sum;
}
void build(int rt, int l, int r) {
a[rt].tag = 0;
if (l == r) {
a[rt].sum = 0;
return;
}
int m = l + r >> 1;
build(rt * 2, l, m);
build(rt * 2 + 1, m + 1, r);
push_up(rt);
}
void update(int rt, int l, int r, int L, int R) { // l, r 是 rt管理的区间, L R是修改的区间, k 是修改的量
// 整个区间都要改变
if (L <= l && r <= R) {
a[rt].sum = (r - l + 1) - a[rt].sum;
a[rt].tag = 1 - a[rt].tag;
return;
}
push_down(rt, l, r); // tag 向下传递
int m = l + r >> 1;
if (L <= m) update(rt * 2, l, m, L, R);
if (R > m) update(rt * 2 + 1, m + 1, r, L, R);
push_up(rt); // sum 向上汇总
}
int query(int rt, int l, int r, int L, int R) {
// 整个区间都要
if (L <= l && r <= R) {
return a[rt].sum;
}
push_down(rt, l, r);
int m = l + r >> 1;
int s = 0;
if (L <= m) s += query(rt * 2, l, m, L, R);
if (R > m) s += query(rt * 2 + 1, m + 1, r, L, R);
return s;
}
int main() {
int m;
cin >> n >> m;
build(1, 1, n);
for (int i = 0; i < m; i++) {
int op, l, r;
cin >> op >> l >> r;
if (op == 0) {
update(1, 1, n, l, r);
} else {
cout << query(1, 1, n, l, r) << endl;
}
}
}