ACCE55_DE21ED

競プロとCTF

JOI難易度8を2日で全クリする

これはなんですか?

基本に立ち返るべく、難易度8をもう一周する事にしました

解説記事ではないので、感想とかを書きます

ネタバレ注意

Shuffle

1回のシャッフルにつき列が分かれて増える数は高々2なので、愚直にシミュレーションしても間に合う事が分かります

シャッフル後のカードは増加列をいくつか持っている形になっているので、それを持ちます

実装辛い...

植木算消えろ!!!

ACコード

散歩

これad-hocで面白い

ある時点で各頂点の向きがどちらかは、最初の向きとその頂点を通った回数によって決まります

各頂点を N 回通る時、その頂点から右と下の頂点へはそれぞれ大体半分ずつ通ります(奇数の場合、最初に向いている方向が1回多い)

よって、N 回目に散歩する時に各頂点がどちらを向いているかが分かるので後は適当にシミュレーションするだけです

ACコード

認証レベル

これ簡単枠じゃないかな

cost1[i]= 事務所1で i 室入るために必要な最小コスト

cost2[i]= 事務所2で以下同文

として、事務所1で入る室数を全探索すれば良さそうな事が分かります

コストは、エレベータの所からスタートしてstd::priority_queueを使うと簡単に実装できます

事務所1,2で同じ実装をするのは面倒なので、関数でやると楽ですね

ACコード

Sequence

要は奇数か偶数かを考えれば良い事が分かります

鳩の巣原理より、周期の長さは高々 (2n-1) × n で、実際はもっと短いので間に合うっぽい?という事が分かります

というわけで周期の長さがいくつかをシミュレーションして、後はバケット法の下位互換(伝わって)をすれば良いです

↓こういうやつ

while(p%n&&p<q){
    ans+=v[p++];
}
while(q%n&&p<q){
    ans+=v[--q];
}
ans+=(q-p)/n*sum;

周期が確定した後に最後のを消し忘れてN回WA出した...

ACコード

Pyramid

これも簡単枠。

std::priority_queueを使って、ピラミッドの高さが高い方から周りに伝播させて行けばいいです

define int long longをしているとMLEします(懲りない人)

ACコード

Abduction

X座標とY座標は独立なので、それぞれimosの要領でDPすれば良いです

配列の再利用をしないとMLE

dpx[H][j]とする所をdpx[W][j]にして、気づくのに1時間かかった...

カス

ACコード

Advertisement

トポソみたいな感じで、上からドバーッと流していけば良い事が分かります

これ、強連結成分分解とは言わない気がする...

ACコード

Distribution

子の中で最も得点の高いパスを親に繋げて、他はそこで打ち切りみたいな実装をすると、O(NlogN)になって嬉しいです

以前やった時はLCA使って実行時間ギリギリで通した記憶...

ACコード

方向音痴のトナカイ

これ難易度9だと思うんですが...

前からやるとTLEするので、後ろからやります

後ろからだと、次にできるやつが高々4通りなので間に合います

やっぱり難しいなぁ...

ACコード

------------------ここまで4/29------------------

Sengoku

以前やった時は面倒な方法をしたのですが、今は45°回転する一般的なテクを知っているのでさほど難しくはないです

重複した線に気をつければ、そこまで難しくはないはず...?

ACコード

a plus b

見た目は簡単なのに...ってやつですね

以前やった時、実装に苦しんだ覚えがあって二度とやるかくらいに思っていたんですが、大して難しく感じませんでした(嬉しい)

ただ、長さが0のものをvectorに入れていたせいでバグって30分溶かしました...(ァ)

ACコード

DNA Synthesizer

ただのやるだけDPに見えますが、実行時間制限が短いです

std::setを使うとTLEしますが、std::unordered_setを使うと余裕で間に合います

set::findだけを使う時はunordered_setを使った方が速いです

Trieでやるともうちょい速いです

ACコード(unordered_set)

ACコード(Trie)

歩くサンタクロース

全点からの距離の和の最小は中央値という有名なやつを利用します

どれか1つだけ取り除く場合、中央値はどう変化するかを考えれば良いです

そんなに難易度8の中ではまぁまぁ難しい方?

ACコード

Deciphering

部分文字列の数え上げ、典型中の典型ですね

define int long longを付けてることでTLEやMLE、難易度8はめちゃくちゃ多いなぁ...

ACコード

Nails

正三角形は嫌なので、傾けて直角三角形にします

あらかじめ加算のスタートとゴールをimosで加算してから斜め方向にimosすればOK!

面白い問題だと思います

ACコード

JOI Flag

ほとんど塗られてないので、適当な枝刈りをすれば良いです

愚直に実装すると大変ですが、工夫すれば楽に実装できます

ACコード

現代的な屋敷

向きが同じ状態の周りのスイッチと、向きの違う同じ場所に対して辺を張れば良いです

1-2-3-4-5のように連なっている場合は、1-3のような辺は必要ありません

あとは適当にダイクストラすればOKです

ACコード

マスコットの片付け

かなりAtCoder寄りの問題ですね...

縦長の長方形を追加する時、大事なのは高さであり、上下にいくつずつあるかはどうでも良いです

なので、DP[i][j] = 既に上下に i マス 左右に j マス追加した場合の数 としてDPをして、後は適当に最初の長方形を作るまでの通り数と上下左右にそれぞれ割り当てる通り数を掛ければOKです

面白い問題だと思います

ACコード

Spy

Nの方の制約がゆるいので、そっちから考えます

ans[i][j] = JOIの i , IOI の j が参加するプロジェクトの個数として、JOIとIOIでそれぞれ下に降りていけばO(N2)です

難易度7でも良いんじゃないかな...

ACコード

Mountain Rescue

難易度8としては珍しいインタラクティブです

割と天才解法だし、難しいと思うんだけどなぁ...

ACコード

Presents

全ての出次数が1という事は、各連結成分が1つの閉路と、閉路に向かって生えている辺のみという事です

閉路に向かって生えているのは全て嬉しさが多い方にできます

閉路の中で、自分と違うのを好む人が偶数の場合、全員を嬉しさが多い方に分配する事ができます(偶数回反転したらもとに戻る)

しかし、奇数の場合は閉路の中の誰かを犠牲にする必要があります

あとはDFSやるだけ

ACコード

フクロモモンガ

最大の懸念は、時間が短いかつ高さが高いという事はあり得るかということです

登る以外は全て時間と同じだけ下がるので一度も登っていないものは関係ありません

また、一度登ったらギリギリの高さまで登ってギリギリ到着を繰り返す事になるので、必ず高さ0になり関係ありません

よって、時間だけを見れば良いことが分かりました

後はダイクストラするだけです

ACコード

財宝

半分全列挙からRange Minimum Queryです

mutliset ... TLEする

Segtree ... ギリギリ間に合う

スライド最小値 ... 余裕で間に合う

ACコード(スライド最小値)

コピー&ペースト2

元の位置を逆算する一般的なテク

ACコード

Bulding3

Building N を見る度に頭痛くなるんですけど...

Building 4がトラウマ過ぎる

必ず使わなきゃいけない数がある場合とない場合があるぞい!

重複に注意

ACコード

遺産相続

クラスカル法を思い出すと、小さい方から貪欲に追加していくだけで最小全域木になる、つまりなるべく番号が小さい人に割り当てるのが最適です

より、連結であるかは単調になり、二分探索が使えます

難易度8の中では割と難しい方なのでは...?

ACコード

屋台

まわりのを既に買ったかどうかを5bitで持つDP

実装鬼畜すぎる...

多分難易度8最難関

ACコード

鉄道運賃

BFSで最短経路で頂点に入ってくる辺の本数を持っておき、それが0になったら消して子に伝播...みたいな事をすると良いです(語彙力)

既に消した辺を二度消すみたいな事をして1WA

ACコード

準急電車

増える量は単調減少なので、単純にpriority_queueに入れて貪欲法でOKです

めちゃくちゃバグらせた...

本番だったらマジでパニックになってそう

ACコード

JOIOI王国

普通にやると実装が面倒になるのですが、Sayaka姉貴の言ってた90°回転を4回やるテクを使うと簡単れふ

ACコード

おわりに

疲れました...

4/29 9問

4/30 21問

一日で終わらせるのはほとんど不可能に近いです

是非挑戦してみて下さい!