let mut pos0 = 0_i64;
for l in &ls {
if *l == 0 {
pos0 += 1
} else {
break;
}
}
// ↓ こう書く方がよかった
let pos0 = ls.iter().copied().take_while(|x| *x == 0).count();
- イベントを Priority Queue に入れる
- この手の問題は、2種類のイベントが同時刻に発生した場合はどちらの処理を優先させるかを問題文をよく読んで判断する必要がある
- 同じ時刻に複数のグループが入店する可能性を忘れてた
- 列が並んでいたら1グループだけ入店させる処理を書いてしまっていた。
- コンテスト中の解法: 累積和を使う
- 反省点
- $\sum_{j=l}^r A_j$ の部分で累積和を考えるのがあまりに遅かった
- まずはどういう解法があるかをいくつか案を出すのが大事。
- 累積和を使う
- 累積和を使わずに $A_i$ の寄与を考えるなど
- 式の展開をしたらよいことに気づくのに時間がかかった。
- この手の問題は閉区間 $[L, R]$ で考えるより、半開区間 $[L, R)$ で考えたほうが良さげ
- 途中 $\sum_{l=L}^R S_l = (R-L) \sum_{l=L}^RS_l$ としてしまい、しばらくミスに気づけなかった(半開区間ならこういうミスは起こりにくい)
- 式の展開 vs 因数分解
- 式の展開
- 式の展開をすると、項は増える代わりに項を構成する要素がシンプルになって扱いやすくなる。項が増えてもその数だけ考察すればいいだけではある。
- 因数分解
- xy=k や xy=0 みたいな式変形ができるときに強い(方程式・不等式がときやすい)
- 前者は約数列挙で $(x, y)$ の組が絞れる
- 後者は $x=0$ または $y=0$ が言える
- 次やること
「ちょうど M 種類」を扱うのは難しい。
M種類以下からM-1種類以下を引くなどの考え方をするとよい?