B - 農場の区画分け / Farm Partitioning 解説 by admin 印刷ページ
Qwen3-Coder-480B概要
与えられた区画分けに対し、各区画の生産力(収穫量の合計)の最大値と最小値の差を求める問題。
考察
各区画は連続した畑から構成されており、各区画の生産力はその区間に含まれる畑の収穫量の合計となる。
素朴な方法では、各区画ごとに \(L_j\) から \(R_j\) までループを回して合計を求めると、最悪ケースで \(O(N \times M)\) の計算が必要となり、制約が \(N, M \sim 2 \times 10^5\) なので時間内に処理しきれない可能性がある(TLE)。
これを解決するために、「累積和」を用いる。
あらかじめ \(S[i] = A_1 + A_2 + \cdots + A_{i-1}\) という累積和配列を作っておくことで、任意の区間 \([L, R]\) の合計が \(S[R] - S[L-1]\) で \(O(1)\) で求められる。
これにより全体の計算量を \(O(N + M)\) に抑えることができる。
アルゴリズム
- 入力を高速に読み込む(
sys.stdin.readを使用)。 - 畑の収穫量の累積和配列 \(S\) を構築する:
- \(S[0] = 0\)
- \(S[i] = S[i-1] + A[i-1]\)
- 各区画について、\(L_j\) から \(R_j\) の区間和を累積和を使って求める:
- 区画の生産力 = \(S[R_j] - S[L_j - 1]\)
- 生産力の最大値と最小値を記録しながら更新していく。
- 最後に最大値と最小値の差を出力する。
例
例えば、\(A = [10, 20, 30, 40]\) で区画が \([1,2]\) と \([3,4]\) の場合: - 累積和: \(S = [0, 10, 30, 60, 100]\) - 区画1の生産力: \(S[2] - S[0] = 30 - 0 = 30\) - 区画2の生産力: \(S[4] - S[2] = 100 - 30 = 70\) - 差: \(70 - 30 = 40\)
計算量
- 時間計算量: \(O(N + M)\)
- 空間計算量: \(O(N)\)
実装のポイント
sys.stdin.readを使って高速に入力を読み込む(Python では重要)- 累積和のインデックスに注意(\(S[0] = 0\)、\(A[i]\) に対応するのが \(S[i+1]\))
- 最大・最小の初期値に注意(最大は十分小さな値、最小は十分大きな値で初期化)
## ソースコード
```python
import sys
input = sys.stdin.read
def main():
data = input().split()
N = int(data[0])
M = int(data[1])
A = list(map(int, data[2:2+N]))
# 累積和を計算
S = [0] * (N + 1)
for i in range(N):
S[i+1] = S[i] + A[i]
max_prod = -1
min_prod = float('inf')
idx = 2 + N
for _ in range(M):
L = int(data[idx])
R = int(data[idx+1])
idx += 2
prod = S[R] - S[L-1]
if prod > max_prod:
max_prod = prod
if prod < min_prod:
min_prod = prod
print(max_prod - min_prod)
if __name__ == "__main__":
main()
この解説は qwen3-coder-480b によって生成されました。
投稿日時:
最終更新: