Range utilities
概要
rangeutilsはNimのSlice、HSlice、BackwardsIndexを、
データ構造内部で扱いやすい半開区間[l, r)へ変換します。
Fenwick Tree、Segment Tree、Lazy Segment Tree、Sparse Table、 Rolling Hashなどで共通利用されています。
import
import atcoder/rangeutils
対応するrange表記
type RangeType =
Slice[int] |
HSlice[int, BackwardsIndex] |
HSlice[BackwardsIndex, int] |
Slice[BackwardsIndex]
長さ8のcontainerでは、次のように正規化されます。
| 表記 | 意味 | [l, r) |
|---|---|---|
2 .. 4 |
両端を含む | [2, 5) |
2 ..< 5 |
右端を含まない | [2, 5) |
2 .. ^1 |
index 2から末尾まで | [2, 8) |
^3 .. ^1 |
末尾相対index同士 | [5, 8) |
^3 .. 6 |
末尾相対の左端 | [5, 7) |
^3 ..< 7 |
末尾相対の左端・半開 | [5, 7) |
^3 ..< 5 |
空区間 | [5, 5) |
0 ..< ^0 |
全区間 | [0, 8) |
^0 ..< ^0 |
末尾の空区間 | [8, 8) |
0 .. ^0 |
clampしないclosed range | [0, 9) |
^kはcontainer.len - kへ変換されます。
したがって^1は最後の要素、^0は末尾の直後を表します。
全区間には0 ..< ^0を使用してください。
0 .. ^0はclosed右端をさらに1増やすため、
通常のデータ構造に対しては範囲外になります。
公開API
type RangeType
type IndexType
template halfOpenEndpoints(
p: Slice[int]
): (int, int)
template halfOpenEndpoints(
container,
p: RangeType
): (int, int)
整数endpointだけのrangeはcontainerなしでも変換できます。
doAssert halfOpenEndpoints(2 .. 4) == (2, 5)
doAssert halfOpenEndpoints(2 ..< 2) == (2, 2)
BackwardsIndexを含むrangeでは、
長さを得るためcontainerを指定します。
let values = @[10, 20, 30, 40, 50]
doAssert values.halfOpenEndpoints(1 .. ^1) == (1, 5)
doAssert values.halfOpenEndpoints(^3 .. 3) == (2, 4)
doAssert values.halfOpenEndpoints(0 ..< ^0) == (0, 5)
データ構造での使用例
import atcoder/fenwicktreeimport atcoder/rangeutilsvar tree = initFenwickTree[int](8)for i in 0 ..< 8: tree.add(i, i + 1)doAssert tree.sum(2 .. 4) == 12doAssert tree.sum(2 ..< 5) == 12doAssert tree.sum(2 .. ^1) == 33doAssert tree.sum(^3 ..< 7) == 13doAssert tree.sum(0 ..< ^0) == 36
既存のsum(l, r)やprod(l, r)などの(l, r)形式も
引き続き利用できます。
境界条件
- 正規化は
O(1)です。 - 結果は常に半開区間
[l, r)です。 - 空の半開区間は
l == rになります。 - endpointのclampや範囲検査は行いません。
- 範囲外のendpointは範囲外の整数へそのまま変換されます。
0 ..< ^0は長さ0のcontainerでも[0, 0)になります。- closed rangeの右端は内部で1加算されます。
- closed右端には
high(int)を使用できません。 - overflow checkが有効なbuildでは、
high(int) + 1は拒否されます。 - 実際のデータ構造が要求する
0 <= l <= r <= lenを満たす必要があります。
計算量
| 操作 | 計算量 |
|---|---|
| 整数endpointの正規化 | O(1) |
BackwardsIndexの正規化 |
O(1) |
| 追加領域 | O(1) |
関連
atcoder/fenwicktreeatcoder/segtreeatcoder/lazysegtreeatcoder/extra/other/sliceutils
検証
専用testで以下を確認しています。
- 4種類すべてのendpoint型組合せ
- closed rangeとhalf-open range
BackwardsIndex^0- 長さ0のcontainer
- 空区間
- clampを行わない契約
- 最大の安全なclosed右端
- checked overflow拒否
- Fenwick Treeの公開range API
- refc / ORC
- Nim 2.2.10 / AtCoder Nim 2.2.4