累積和
競プロで知ったことのメモ。
簡単な概要
累積和とは前処理をすればの計算量で、区間の合計を求めることができるアルゴリズム。
例えば、長さの数字の配列があるとする。
| |
|
|
|
|
|
|
|---|---|---|---|---|---|---|
| 2 | 6 | 1 | 9 | 5 | 8 | 4 |
から
までの区間の合計を求めたいというときは、単純に
から
までをループ(
)すれば求めることができる。
配列が長かったり、~
、
~
、
~
.....と区間の合計を求める回数が例えば
回もある場合、
かかるので処理にとても時間がかかってしまう。
累積和を使うと前処理にかければ、区間の合計を求める計算量は
で済む。
どんな前処理かというと、以下のような大きい配列を用意する。
| |
|
|
|
|
|
|
|
|---|---|---|---|---|---|---|---|
| 0 | 2 | 8 | 9 | 18 | 23 | 31 | 35 |
この配列の中身、には
までの区間の合計が入っている。
- ...
- ...
- ...
この配列を用意すれば、から
までの区間の合計は
という式で求めることができる。
には
から
の合計が入っているので、
から
の合計が入っている
を引く。
となる。
実装
上の例、から
までの区間の合計を求めるプログラムをC#で実装してみる。
void Sample() { var N = 7; var a = new int[7] { 2, 6, 1, 9, 5, 8, 4 }; var s = new int[N + 1]; var left = 2; var right = 6; for (int i = 0; i < N; i++) { s[i + 1] = s[i] + a[i]; } Console.WriteLine(s[right + 1] - s[left]); }