はじめに
こんにちは。nsubaruです。
アチアチ5完62分でレート+51!過去最高パフォ1544を記録しました! 50を越えるのは2025/01/04ぶりで激アツです!水目前にして伸びしろを感じています。
(代表は Codeforces や他のコンテストには参加しているようですが今回もABCには不在でした。)
結果サマリ
-
WCPC参加人数: 6人
-
各問題の最速解答者(ペナルティ無し):
| 問題 | 参加者名 | タイム | 言語 |
|---|---|---|---|
| A | ShoboiNamae | 1:00 | C++ |
| B | ShoboiNamae | 3:47 | C++ |
| C | kotomiko | 17:08 | C++ |
| D | nsubaru | 33:02 | Java |
| E | nsubaru | 61:58 | Java |
| F | - | - | - |
| G | - | - | - |
今週の出題
ABC462-A
問題文を表示
問題文
英小文字と数字のみからなる文字列 が与えられます。
から数字である文字だけを取り出し、元の順序のまま並べた文字列を求めてください。
制約
- は英小文字と数字のみからなる長さ 以上 以下の文字列
入力
入力は以下の形式で標準入力から与えられる。
出力
答えを出力せよ。
文字が数字かどうか判定する問題です!
char値は比較できるので ‘0’ <= && <= ‘9’ となる を出力するだけです!
ABC462-B
問題文を表示
問題文
人 から人 の 人がギフトを送り合いました。
人 は人 の 人にギフトを送りました。
に対し、人 にギフトを送った人を全て求めてください。
制約
- 入力される値は全て整数
入力
入力は以下の形式で標準入力から与えられる。
出力
行出力せよ。
行目には、人 にギフトを送った人の番号を昇順に (ただし は人
にギフトを送った人数)としたとき、以下の形式で出力せよ。
前回に引き続き、配列のindexを使って数を数える系の問題です。
しっかり誤読して、人にギフトを送った人数を出力すると思っていたら、ギフトを送った人を出力するっていう、ちょいめんどくさい問題でした。
ちなみにこの前知ったのですが、行ごとに長さの違う2次元配列(正確には要素自体が配列となる配列)はジャグ配列と言うらしいです。
ABC462-C
問題文を表示
問題文
次元平面上に点 から点 までの 個の点があります。点 の座標は
です。ここで、 はそれぞれ の順列であることが保証されます。
左下の頂点を 、右上の頂点を とする 軸に平行な辺と 軸に平行な辺のみからなる長方形の内部(辺上を含まない)に点
から点 までの 個の点をどれも含まないような の個数を求めてください。
制約
- はそれぞれ の順列
- 入力される値は全て整数
入力
入力は以下の形式で標準入力から与えられる。
出力
答えを出力せよ。
順列とかなんとか書いていますが、とりあえず条件を満たすことのできる要素の数え上げの問題です。
ここでもしっかり誤読を発動し、右上となる頂点は 上のグリッド内から任意の点を選ぶものだと思って解いていたのですが、 そうではなくて、右上となる頂点は入力で与えられる点集合から選択するということでした。
まあ何はともあれ、二次元配列をソートして、頂点を辺に含まないようにだけ注意して後は小さい順に見ていくだけです。
ABC462-D
問題文を表示
問題文
とある館で殺人事件が起きました。犯人の候補は 人おり、彼らを人 、人 、、人 と呼びます。
人 は時刻 に館に入り、時刻 に館を出て、ほかの時刻には出入りしませんでした。
犯行について以下のことが分かっています。
- 犯人はちょうど 人いる。
- 犯行はある整数時刻 に開始し、 単位時間かけて行われ、時刻 に完了した。
- 犯人は 人とも犯行開始から犯行完了まで常に館にいた。(犯行開始と同時に館に入ったり、犯行完了と同時に館を出たりしたかもしれない。)
人の犯人候補の中に犯人が 人ともいると仮定したとき、 人の犯人と犯行開始時刻の組としてありうるものは何通りあるでしょうか。ここで、 人の犯人には順番を付けません。
制約
- 入力される値は全て整数
入力
入力は以下の形式で標準入力から与えられる。
出力
人の犯人と犯行開始時刻の組としてありうるものの個数を出力せよ。
犯人候補から2人選んで、それが犯人と仮定できる組み合わせを求める問題です。 ここでも誤読して人の組み合わせだけかと思ったら、人と時間の組み合わせを求めないといけない問題です。
まあそれはさておき、こういう区間系の問題と組み合わせ系の問題で考えることは以下の2点だけです。
- 区間系問題の定石として、入室時間でソートをかけた後、有効な区間(退室時間)をPriorityQueueで管理すること(イベントソートとか言うらしいけどわからない)。詳しくは↓
- 組み合わせ系の問題について、組み合わせは の式を使うのではなく、ある 番目の値とそれより前に出てきた有効な値集合との組み合わせだけを考えること。
これらを考えると、ある 番目の値と共犯の可能性がある値はPriorityQueueに入っているので、答にその要素数を加えていくだけになります。
まあ誤読していたので実はなのですが、今回の問題は時間との組み合わせを求めないといけないらしいので上記の2が使えません。 しかしここまでの考えを利用すると、以下のような手順で解くことができます。
- 時間でループを回し、現在の時間 が入室時間になっている人がいればその人の退室時間をPriorityQueueに入れる。(入場)
- 次にPriorityQueueから、 より小さい値、つまり現在の時刻から犯行が行われた場合犯人でない人を取り除く。(退場)
- そして最後に、このPriorityQueueの要素数を用いて二項係数を求める。
結構綺麗だと思いませんか?有効な区間を保持しながらループを回すというこの解法はけっこう好きです。(工夫すれば入退室時間の値がもっと大きくても多分解けるので)
ABC462-E
問題文を表示
問題文
整数 が与えられます。
二次元平面上にコマが置かれています。はじめコマは座標 にあります。
あなたは以下の操作を 回以上何回でも行うことができます:
- 今コマがある座標を として、座標 のいずれかにコマを移動させる。
回目 に行う操作にかかるコストは の偶奇によって異なり、それぞれ以下の通りです:
- が奇数のとき:今コマがある座標を として、座標 に移動させる場合のコストは 、座標 に移動させる場合のコストは である。
- が偶数のとき:今コマがある座標を として、座標 に移動させる場合のコストは 、座標 に移動させる場合のコストは である。
コマを座標 に移動させるために必要なコストの総和の最小値を求めてください。
個のテストケースが与えられるので、それぞれについて答えを求めてください。
制約
- 入力される値は全て整数
入力
入力は以下の形式で標準入力から与えられる。
番目 のテストケース は以下の形式で与えられる。
出力
各テストケースに対する答えを順に改行区切りで出力せよ。
E問題はグリッドの最短距離を求める系の問題でした。 450点で解ける可能性は全然あるなと強気で挑んだのと、直近でICPCの模擬の問題で似たようなのを解いたことが功を奏し無事ACを勝ち取りました!
まず、問題を見ると複数テスト系の問題かつ の制約が と、おそらく かなと考えました。
次に極端なケースを考えると、 のとき移動回数の偶奇で方向ごとのコストが変わるので、小さい方のコストのみを使用して最短距離を移動できるため、 になります。
では のとき、目的値に向かって最短な移動を繰り返した後、残りの縦(横)の直線移動のコストをどのように最小にするかを考えます。 これは とすると、そのまま直線にコスト で 1回で移動するのと、1マス分膨らんでコスト の移動を3回するのとを比較し、小さい方で移動させるだけです。 つまり、上一回で移動できるところを、右上左のようにして同じコストのみを使った移動に変えた方が良いかを考えます。
結局のところもっと他の回り道の方法(桂馬みたいな動きをするとか)を考える必要があるのかと思いましたが、シンプルなものを考えるだけで十分でした。
ABC462-F
問題文を表示
問題文
英大文字のみからなる文字列 が与えられます。
高橋君の目標は、 の文字のうちいくつかを置換することによって、 が ABC を部分文字列として含む個数をちょうど
個 増やす ことです。
このようなことが可能か判定し、可能な場合は目標を達成するために高橋君が最低何文字置換する必要があるか求めてください。
個のテストケースが与えられるので、それぞれについて答えを求めてください。
置換とは
の文字のうちの つを置換するとは、 をみたす整数 を つ選び、 の
文字目を任意の英大文字 字 で置き換えることを指します。
ただし、 で の長さを表すものとします。
部分文字列とは
の部分文字列とは、 の先頭および末尾からそれぞれ 文字以上削除して得られる文字列のことを指します。
つの部分文字列は、 から取り出した場所が異なれば、文字列として等しくとも区別して数えられます。
制約
- は英大文字のみからなる長さ 以上 以下の文字列
- それぞれの入力において、各テストケースの の長さの総和は 以下である。
- は整数
入力
入力は以下の形式で標準入力から与えられる。
は 番目のテストケースを表す。
各テストケースは以下の形式で与えられる。
出力
行出力せよ。
行目 には、 個目のテストケースに対する答えを出力せよ。
ここで、各テストケースに対する答えとして、高橋君が目標を達成することが不可能な場合は
を、そうでない場合は目標を達成するために置換する必要のある文字の個数の最小値を出力せよ。
今回はF問題まで考えれたので、少し書きます。コンテスト後、バグ取りなどで少しAIに頼りましたがほぼ自力AC出来ました。
40分近く残してEをACでき、今回は余裕をもってFを始めれました。最初に見たときにABCを 個増やすだけ、しかも が小さいからただ前からABCを構築していく DP をするだけではと思いました。
結局の解法はこの考えをしっかり詰めるだけではあるのですが、テストケースを見てみると既存のABCを破壊してそれをずらしてから、ABCを再構築するみたいなケースがあり少しめんどくさい感じがあります。
そこでまあTLEにはなるだろうとは思いつつ、とりあえず 文字列に含まれる既存のABC+k 個のABCを作成するための最小コストを求める DP を作成し、見事にTLEにはなりました。
ここからしっかりにするために、普通の DP だとi番目までにABCをj個作成するための最小コストみたいにするところを、 ABCの増減が起こることを考え、i番目までにABCをj個増やすための最小コストという DP とします。
考える状態数は以下の3つになります。
:i番目までの文字を用いて、ABCをj個増やしたとき最後の文字がAとなるときの最小コスト。
:i番目までの文字を用いて、ABCをj個増やしたとき最後の2文字がABとなるときの最小コスト。
:i番目までの文字を用いて、ABCをj個増やしたとき最後の文字に意味をなさないときの最小コスト。
ただ先ほども言った通り今回はjが増減するため、負の値になることを考慮する必要があったり、遷移の式を考えるのがだるかったりするので順当に難しい問題でした。
ABC462-G
G問題は見てすらないです。そのうち解くから待ってろ。
最後に
問題の配点通りの綺麗な問題セットで難易度も順当だなーと感じました。
今回は結構上振れパフォを出せましたが終わって見ればまだまだ改善できた点はあり、B・C・Dではいずれも誤読したし、Eも簡単な解法だったのでもっと速く解けたなとか。。。 まあでもここまでの勝ちは久しぶりですし、水目前にしてこのレートの上がり方が出来るのは結構凄いんじゃないかと、ここは素直に自分をほめたいと思います。
次回は入水記事で会えればと思います!nsubaruでした。