📜  门|门模拟 2017 |第 52 题(1)

📅  最后修改于: 2023-12-03 15:28:49.261000             🧑  作者: Mango

门|门模拟 2017 |第 52 题

题目描述

你需要写一个程序来模拟开门和关门的过程。假设有 $n$ 个门,每个门都有一个初始状态:要么是打开的,要么是关闭的。你的程序需要对这些门进行 $m$ 次操作。每次操作都是应用于一段连续的门。

操作可以是以下两种之一:

  • 切换区间内所有门的状态(打开的变成关闭的,关闭的变成打开的);
  • 查询区间内打开的门的数量。

你需要将每次查询操作得到的结果输出到标准输出上。

输入格式

输入文件的第一行包含两个整数 $n$ 和 $m$,分别表示有 $n$ 个门和 $m$ 次操作。

接下来的一行包含 $n$ 个用空格分开的整数 $c_1,c_2,\ldots,c_n$,其中 $c_i$ 表示初始时门 $i$ 的状态。

接下来 $m$ 行,每行描述一个操作。

对于第 $i$ 行($1 \le i \le m$),不妨设为形如 $T\ \ell\ r$,表示一个操作,其中:

  • 如果 $T = 0$,则表示切换区间 $\ell$ 到 $r$ 中的所有门的状态(即打开的变成关闭的,关闭的变成打开的);
  • 如果 $T = 1$,则表示查询区间 $\ell$ 到 $r$ 中打开的门的数量。
输出格式

对于每个查询操作,输出一行一个整数,表示区间内打开的门的数量。

输入样例
5 5
0 1 0 1 1
1 1 5
0 2 5
1 1 5
0 3 3
1 3 3
输出样例
3
3
1
数据范围

$1 \le n \le 10^5$,$1 \le m \le 10^5$,$0 \le c_i \le 1$,$1 \le \ell \le r \le n$。

解题思路

本题需要实现两种操作:

  • 区间取反
  • 区间求和

可以采用树状数组来完成。

首先预处理,记录前缀和 $s_i$,表示第 $1$ 到第 $i$ 个元素的和。

对于操作 $T\ \ell\ r$,如果 $T = 0$,则相当于将区间 $\ell$ 到 $r$ 的元素全部取反,可以使用前缀和数组的差分数组来维护。如果 $T = 1$,则相当于求出终点 $r$ 的前缀和与起点 $\ell - 1$ 的前缀和的差值。

时间复杂度为 $O(m \log n)$,空间复杂度为 $O(n)$。