AtCoder Grand Contest 020:B - Ice Rink Game
問題
https://atcoder.jp/contests/agc020/tasks/agc020_b
考え方
考えていたこと
ナイーブに考えると 回目のラウンド前にいた人数を とするとラウンド後は となることは分かる。1 回目のラウンド前にいる人数を として を順に 回適応すると最終的な人数が決まる。 回適応したときの結果を とすると求めるべき解は を満たす最小/最大の となる。
はある区間上に存在することになるから二分探索で求められる... と考えたが、単純に評価関数を であるかどうかとする二分探索はできない。区間であるから条件を満たさない区切りが区間の大きい場合と小さい場合の 種類存在するためである。
三分探索とかいけるか?と思ったけど、仮に条件を満たす区間の値を としてそうでない区間の値を とすると、そうでない区間がすべて になるので正しく区間を絞ることができないのでダメである。
解説見た
を用いることになる。
直感的には に単調性があると想定できるが、単調性がわからないと以下の評価関数を定義することができなさそう。一応示すと以下のようになる。
に単調性があることから以下が言える。
- なる については単調であって、ある値 までは条件を満たし、 よりも大きい値は条件を満たさない
- なる については単調であって、ある値 までは条件を満たさず、 よりも大きい値は条件を満たす
よって、それぞれの最小/最大値が二分探索で求められることになる。
Submission #4388322 - AtCoder Grand Contest 020
どこに着目して考察するべきだったか
評価関数を工夫すると二分探索が適用できるようになる。区間の最小値、最大値を二分探索で求めたいときには応用できるかもしれない。
何がバグっていたか
得た知見(典型ポイント)
- 二分探索の評価関数を工夫する
- ある値x以下 かつ ある値以上 は ある値
類題
AtCoder Grand Contest 006:B - Median Pyramid Easy
問題
https://atcoder.jp/contests/agc007/tasks/agc007_b
考え方
の場合は中央値になりえないので必ず NO
になる。そうでない場合、例えば の場合は可能かどうかというと可能である。 で実験すると容易に分かる。
上の段の中央値になる場合の条件について考えていこう。
1列目 | 2列目 | 3列目 |
---|---|---|
- | 2 |
- |
* |
* |
* |
まず上の段で 2
になる場合は、必ず下の段(簡略のためにソート後としておく)の真ん中の値は 2
になる。そうでない場合は上の段の中央値になりえない。また少なくとも 1 つは 2
以下の数になっていて、少なくとも 1 つは 2
以上の数になっている。
このように構築すると上の段の真ん中の値は 2
になって、上の段の真ん中左の値は 2
以下の数になる。上の段の真ん中右の値は 2
以上の数になっている。よって最終的には 2
が一番上の数になる。
つまり、構築する数列を とし、一番下の段の中央の index を とすると が必要条件である。十分条件ではない(一番上の数が だからといって が満たされるわけではない。一番下の関係ないマスは任意に埋めていくだけでOK。
Submission #4383041 - AtCoder Grand Contest 007
どこに着目して考察するべきだったか
実験をする。必要条件を考える。
何がバグっていたか
得た知見(典型ポイント)
類題
AtCoder Grand Contest 007:B - Construct Sequences
問題
https://atcoder.jp/contests/agc007/tasks/agc007_b
考え方
えー、難しい...
の順列 の順番になるように を構築する。その際に は単調増加で は単調減少になるようにする必要がある。
いろいろな条件をいっぺんに考えることが難しいときは、ひとつずつ考えていくのがよさそう。
まずは は忘れて、 だけで条件を満たす数列を構築するとしよう。 としておく。これは とすると が単調増加であることを満たす。数列の項がすべて または である数列の累積和をとると単調性が満たされるので累積和をとることを考えよう。そうすると について単調増加になる。
さて累積和を取る過程の をする際に に足す分の を から引くことにする、つまり とすると となって は によって定まることがわかる。したがって とした を仮定しても は単調増加であることに変わりがない。具体的には最初に構築した が保たれる。
について考えよう。 であることから はすでに単調減少になっていることが分かる。ただし は になりうる。構築すべき数列は であるので、 を に一様に足すことで数列の大小関係を維持したまま、 とすることができる。
よって上記のような手順で数列 を構築すると解が求められることになる。
Submission #4383041 - AtCoder Grand Contest 007
どこに着目して考察するべきだったか
差分をキャンセルするという考えにいたると解けるかもしれない...
何がバグっていたか
得た知見(典型ポイント)
類題
- D - Non-decreasing 数列の累積和に一様に値を足す考えは似ています。
AtCoder Beginner Contest 119:D - Lazy Faith
問題
https://atcoder.jp/contests/abc119/tasks/abc119_d
考え方
各クエリに対して ないしは で答えないといけない。神社用と寺用のTreeSet(二分探索木)に各 をあらかじめ入れておけばクエリごとにある位置 に対して左右にある最短の神社と寺の位置を求めることができる。
あとは神社と寺を訪問するパターンを網羅すれば最短距離を求めることができる。右の神社→左の寺...など全 パターンある。
Submission #4380845 - AtCoder Beginner Contest 119
実装テクとしては右端と左端に番兵 () 程度の値を入れてしまうのが楽。
どこに着目して考察するべきだったか
何がバグっていたか
得た知見(典型ポイント)
類題
AtCoder Grand Contest 004:B - Colorful Slimes
問題
https://atcoder.jp/contests/agc004/tasks/agc004_b
考え方
典型っぽい。ある変数を固定すると、最適な操作が見えてくる問題。
何を固定するか?
最小の秒数を 秒として二分探索
- 「 秒で全色のスライムを集めることができるか?」というYes/No問題に切り替える
- しかし、結局最適なスライムの集め方の考察が必要で問題が進んでいない
魔法の回数を とする
- あるスライム を集めるときの最小のコストは で求められることになる
- 各スライムについて、上記の方法で最小コストを求めれば解ける
よって上記から魔法の回数を 回使うとすると、各スライムを集める秒数の最小値を求められることになる。区間 の秒数の最小値はセグメントツリーを用いることができるし、 の小さい値から考えることで自然に求めることもできる。セグメントツリーを使った場合は計算量は となる。
どこに着目して考察するべきだったか
魔法の回数を固定しないとはじまらない。
何がバグっていたか
得た知見(典型ポイント)
- ある変数を固定して考える
類題
AtCoder Grand Contest 005:B - Minimum Sum
問題
考え方
式だけみるとぱっと何を求められているかわからないので、まずはナイーブに の実装で実験してみる。そうすると区間の数について最小になる要素を求めて、その総和を求める問題であることが分かる。
さて、区間の数をまとめて計算したい。「最小値が になる区間が数列上にいくつ存在するか?」という問題を考える。これが高速に求められれば と区間の数 を掛けて、その総和を計算すれば良い。
サンプル3を例に考える。数列は以下のように与えられている。1-indexed で考えていくことにする。番兵として一番右と左に -1
があることにする。
8 -1 5 4 8 1 2 6 7 3 -1
このとき数列の要素 が最小値になる開区間の左端と右端の index はどこになるか、というと左端の値は で 、右端は で となる。 であるから、区間の左端の候補の数は で右端の候補は である。よって 個の区間で最小値が になることが分かる。
ある値 を考えたときに 未満の要素の右端の最大の index と左端の最小の index を求める必要がある。これは値の小さい値から数列上の index を TreeSet に含めていくようにして求めていくと、求める前には必ず今考えようとしている よりも小さい数の index しか TreeSet 上に存在しないので左端と右端の index が で求められることになる。
Submission #4362828 - AtCoder Grand Contest 005
どこに着目して考察するべきだったか
小さい値から考えていくことで候補の index が高速に求められることに気づく必要がある。
何がバグっていたか
得た知見(典型ポイント)
- 小さい値から貪欲
類題
yukicoder:No.794 チーム戦
問題
https://yukicoder.me/problems/no/794
考え方
きれいな問題で好き。 はソートしても問題がないのでソートする。マッチングする際に が大きい値ほど候補になる相手が厳しく、候補が絞られるので が大きい値から考えていく。
サンプル1 の場合ソート後の数列で考えると以下のようになっていて
4 6 1 2 3 4
の候補になれる数は までである。
番目について考える時、候補の相手は二分探索で求めることができる。 の範囲に対して 以下の最大の要素のindex を求めれば良い。 は偶数なので、 ペアを作れば良い。二分探索する回数は である。また後ろから考えて、すでに 人ペアを作っている時で 番目について考える時、その候補に含まれる数のうち、 人はすでにペアになっているので候補の対象にはなりえない。よって、 分は候補の数から差し引く。
#318810 No.794 チーム戦 - yukicoder
実装ポイント
二分探索で求まるのは index の値であって、今回は数列を 0-indexed でとっているので、index の値に+1 する。ある数 以下の最大の index は upperBound(int[] a, int x) -1
で求めることができる。
どこに着目して考察するべきだったか
ソートして問題ないのでソート、条件の厳しいほうからマッチング。
何がバグっていたか
mod をとることを忘れない。
得た知見(典型ポイント)
- ソートしても問題がない
- 条件の厳しい値から考えていく
類題
- B - Powers of two 条件の厳しい要素からマッチングを考えます。