ABC291 参加記

7完86:01 + 1ペナ 261位

Gで詰まりすぎ&Ex解かれすぎ

A camel Case

isupper, islower忘れがち、 'A' < S[i] && S[i] < 'Z'でやった

(AC 1:13)

 

B Trimmed Mean

スキーとかのあれ、ソートして足すだけ

setprecision久しぶりな気がする

(AC 3:42)

 

C LRUD Instructions 2

setにpairをいれて判定する、ほぼ同じようなの解いた気が??

(AC 6:24)

 

D Flip Cards

無限にやった、裏返したかもつDPやるだけ

(AC 10:45)

 

E Find Permutation

こういうのどこまでが必要十分かわからないがち

 

ざっくり考えると、「i より jのほうが大きい」という情報が与えられて、それを満たすものが一意か判定せよ、ということなのでそもそもの「それを満たす順列は?」を考えると、トポロジカルソートをすればいいことがわかります

ということで、「トポロジカルソートが一意ですか?」という問題になります

 

トポロジカルソートを考えると、それぞれの時点で「入次数が0」のものが次に来る候補になるので、「一意になる = 次に来る候補が1通り」であると考えられます

あとは、実際にトポロジカルソートをしてそのときのqueueに値が1つだけか判定すればよいです

(AC 23:25)

 

F Teleporter and Closed off

いつものFよりはかなり簡単に感じた

 

「iを除いたときに」というタイプの問題では、両側から計算しておいてそれをくっつけることが多いです

今回はそれがドンピシャで使えて、「1~iまでの最短回数」「i~Nまでの最短回数」を求めておきます

「i~Nまでの最短回数」は愚直にやると全体でO(N^2 M)になりますが、Nから逆側にたどることで全体でO(NM)にできます

 

「1~iまでの最短回数」「i~Nまでの最短回数」がわかれば、あとはそこまで大変ではなくて、ありえるところを愚直に試します

iを使わないということは、「どこかでiをまたぐ」ことになるのでどこでまたぐかを全探索します

M≦10なので左側10個、右側10個だけみてあげればよいです

到達できない場合のINFをintで管理していると、INF+INFでオーバーフローする可能性があるので注意です(1敗)

(AC 36:25)

 

G OR sum

Fまでサクサクだったので、わくわくしながらGをみます

「動かしながら計算した時の値のmax, min」という抽象化をすると、過去の問題に近いものがあります

F - Substring 2

 

こういう形に帰着できないか考えていきます

畳み込みの形を用いるのであれば、反転させた方がindexの都合がよさそうなので、Bのindexは反転させることにします

 

N = 3の時で考えてみます

     0 1 2 3 4 5 

A : 1 2 3 1 2 3

B : 7 6 5 7 6 5

という感じでそれぞれ2倍にしておいてみます(実はBは2倍にしない方が楽です)

i+j = 0のとき

(1|7)

i+j = 1のとき

(1|6) + (2|7)

i+j = 2のとき

(1|5) + (2|6) + (3|7)

i+j = 3のとき

(1|7) + (2|5) + (3|6) + (1|7)

i+j = 4のとき

(1|6) + (2|7) + (3|5) + (1|6) + (2|7)

...のようになります

 

こうすると、Aに対してBはきちんとcyclic shiftしていることがわかります

求めたいものは i+j = N-1 ~ 2N-2の値で十分です

ただし、i+j > N-1のときは余分なものがついています

i+j = Kのときに、i+j = K-Nの部分だけ無駄なのでこれを取り除いてあげればよいです

 

方針としては、畳み込みをして(Ai|Bi)の和を高速に求めればよさそうだとわかります

ただし普通の畳み込みでは(Ai|Bi)であるOR演算をうまく扱えません

 

ここで先ほどのSubstring 2を改めて考えてみます

Substring 2では0,1に置き換えることでAND演算を計算していました

今回はORですが、0または1のA,Bに対して

「A OR B = 0」 = 「notA AND notB =  1」であることがわかります

これを用いてORをANDに変換できます

つまり、1つのbitにのみ着目した時、bitを反転させた結果AND演算が0でなければ、もともとのOR演算の結果は0になります

 

この0,1をうまく扱うためにはbitごとに計算しないといけないですが、bitごとに5回畳み込みをすることで、OR演算の結果を計算できます

i+j = N-1 ~ 2N-2の値を各bitに対して計算してあげて最大値をとれば解けます

(AC 86:01)

 

総括

7完うれしいけど、重心分解そんなに解かれる?

ABC289 参加記

6完90:58 + 1ペナ 230位

GのCHT忘れすぎてて思い出すのに時間かかった

A flip

さすがにやるだけですね~、めっちゃ簡潔にする方法も言語によってはありそう

(AC 2:15)

 

B レ

むず、問題文をほんとうに信じ込むことでBでUnionFindを使うことになりました

まあD問題と思えばいいだけなので、UnionFindして後ろからたどっていきます

(AC 6:22)

 

C Coverage

そういえば久しぶりのbit全探索ですね

考察自体はほとんどなく...

(AC 9:12)

 

D Step Up Robot

前回のDとの温度差よ

ほんとうにDPやるだけでした、これなら最短回数求めさせてもよさそうだけどね

(AC 13:31)

 

E Swap Places

これも過去に類題があるので考察もあんまりしなかった

F - Construct a Palindrome

 

上の問題を考えると、(高橋くんの位置、青木君の位置)をペアとした頂点をN^2個つくり、そこでBFSをすればいいことがわかります

辺もそんなに貼らなくてよさそうなので信じて投げると通ります

マルチテストケースなのに、初期化を忘れて1ペナ...

(AC 28:02)

 

F Teleporter Takahashi

順位表で全然解かれていない&無限にペナを出しそうな見た目をしていたので避けました

こういうの時間内で解くの大変だよね

(AC --:--)

 

G Shopping in AtCoder store

解けそうな見た目しているので考えます

まずBをソートしても問題ないので、ソートしておきます

とりあえず全員に買ってもらうとすると、(B[1] + C[j]) × N円得ることができます

その状態から、i人分諦めたとしてどうなるか差分を考えてみましょう

諦めた人のぶん(B[1] + C[j]) × iはマイナスになります

一方で、N-i人はまだ買ってもらえるので、(B[i] - B[1]) × (N-i)だけプラスになります

 

よって、i人分諦めたときに「全員買ってもらう」状態からどのくらい得するか?は

(B[i] - B[1]) × (N-i) - (B[1] + C[j]) × iで表されます

ここで、jが関連しているのはC[j]×iの部分だけであることが分かります

つまり、Bを用いる部分は使いまわすことができます

 

ざっくりした式を考えると、(Bから計算できるもの) - C[j]×iになって、これを最大化すればよいです

複数の一次関数から最大化するこの形の問題は、CHT(Convex Hull Trick)で解けることが知られているので、それぞれの一次関数をあらかじめ計算してあげて、CHTでクエリに答えるとよいです

(AC 90:58)

 

総括

7完安定しない

ABC288 参加記

6完99:44 210位

D通したのギリギリすぎるけど、なんとかイベント圏内には入った

こんなにたくさんの暖色どこに隠れていたんだ...

A Many A+B Problems

いつもの、足すだけ

「実はオーバーフローします、ペナするやつは決勝にお呼びじゃないよ~」

みたいなのあるかと思ったけど、そんなことはなく

(AC 1:19)

 

B Qualification Contest

こうなってしまうとAにあってもよさそう

先頭K個だけ取り出して、sortすればおわり

(AC 2:54)

 

C Don't be Cycle

またサイクルだ~

連結成分ごとに(辺の数) - (頂点の数) + 1なので、UnionFindを使ってこれらを管理すればよいです

あんまりコーナーはなくてよかった

(AC 9:00)

 

D Range Add Query

こっからが予選の本番!!!Dにこの重さがあるとしんどい...

 

まず、考えることとして左からつじつまを合わせていって最後のK個で判定すればいいかな?と思うんですが、愚直にするとO(NQ)かかります

途中で勘違いして、[i~r]すべてに加算できると思ってしまい変な考察をしてしまいます

累積和的にできるな~と思ったんですが、そもそも考察が違っていたのでサンプルも合わず沼に...

予選の都合上、点数高いところをとったほうがいいかなと思ったので、30分くらい粘ってわからず撤退しました

 

===== E,Fを解いてもどってきてから =====

 

どうせならここを通して順位をあげたいので、なんとかあがきます

頭が混乱してしまったので、もう愚直に実験してみることにします

そうすると、左から愚直に操作をしたときに右側のK-1個について以下のことが成り立ちそうだと思いました

・r-K+1と余りが等しいものはすべて足されている

・iと余りが等しいものはすべてひかれている

 

もう時間がないので、これを信じるしかないのでindexをKで割ったあまりで分けて、累積和をK個用意します

そして、上の2つの和ともともとの値を比較した結果、一致しているならOKとしました

サンプル1を試すとあったので、投げるしかない!と投げたら通りました

Submission #38623914 - Toyota Programming Contest 2023 Spring Qual A(AtCoder Beginner Contest 288)

(AC 99:44)

 

E Wish List

Dが解けないので悲しくなりながらみます

問題内容や制約が明らかにDPしてくれ~~って言っているので、DPをします

dp[i][j] := i番目の荷物まで考えたときに、i以下のものをj個買っているときの最小値

と定義します

 

遷移を考えます

もし、買わないなら 単純に dp[i+1][j] = min(dp[i+1][j], dp[i][j]) でよいです

買う時が少し複雑です

もし今j個買っているなら、用いるCの値はCi-jになります

ただ、必ずしもCi-jを用いる必要があるわけではありません

たとえば、j-2個買ったときにiを先取りして買ってしまえば、Ci-j+2を用いることができます

よって、Ci-j ~ Ciのどれかを好きに使えるのでこの最小値を使えばよいです

本番だとしっかりとは証明していないんですが、そうでもないとDPが回らなくて解けなそうなので、信じるとサンプルが合って通りました

区間最小値何も考えずにminセグ木を使ったけど700msくらいで間に合ってよかった

(AC 52:49)

 

F Integer Division

こういうタイプの問題、よく桁DPであるやつだな~と思います

今回はいわゆる桁DPとは違うんですが、

dp[i] :=i桁目までのときの答え

とするDPが使えそうだなと思って考察します

 

サンプル(の一部)を例にして考えてみます 

S = 23を考えてみましょう

dp[1] = 2なのは自明です(S = 2のときなので)

dp[2] = 23 + 2×3 = 29となりますが、これをもう少し抽象化すると、

dp[2] = dp[0]×S[1:2] + dp[1]×S[2:2] (ただしdp[0] = 1とする)

となります

 

ここから一般化すると

dp[i] = ∑k=0~i-1 (dp[k] × S[k+1:i])

で計算できることが分かります

これを愚直にするとO(N^2)になるので、高速化しましょう

こういうタイプの高速化として「式の形が大きく変わらない」というところに注目します

 

dp[i] = ∑k=0~i-1 (dp[k] × S[k+1:i])

dp[i+1] = ∑k=0~i (dp[k] × S[k+1:i+1])

の2つの式を見比べると、変わったところは「kの値が1増えた」「Sの長さが1増えた」の2点です

kの値が1増えた部分は愚直にそのときの値を足してあげればよいです

Sの長さが1増えた部分も実はそんなに複雑ではなく、10倍して末尾の数字を加えてあげるだけです

よって、O(1)で更新ができるため、全体でO(N)で解くことができます

お気持ちは書いたんですが、細かなところは公式解説などを見るといいと思います

(AC 83:50)

 

G 3^N Minesweeper

見る時間なかった...

(AC --:--)

 

総括

QualBで決勝にいきたい

ABC287 参加記

6完41:05 234位

G解けたと思って40分バグらせたのかなしすぎる

A Majority

もうforのあるAにも慣れてしまった、数えるだけ

(AC 2:16)

 

B Postal Card

下3桁しか見なくてよいので、あらかじめ余分なところを落としてしまいます

そしたらただ一致判定するだけ

(AC 5:03)

 

C Path Graph?

これこわい

とりあえず、N-1=Mでないといけないのはいいですが、変な形になっていないか確かめる必要があります

もっと楽なやり方ありそうだけど素直に

・次数が1のもの2つ残りは2

・全体が連結である

をそれぞれ判定しました

(AC 13:28)

 

D Match or Not

これもABC-D典型ですね

左右から挟んでいるので、左右それぞれの値を前計算しておけばいいです

累積和とかでもよくあるやつ

(AC 20:20)

 

E Karuta

なんでE?と思ったけど、想定解がむずかしかった

一番LCPが大きくなるのは辞書順で隣り合うものになります

よって、ソートして愚直に隣だけ比較すればよくて、それぞれの文字列の比較回数が2回ですむので、全体でO(NlogN)となります

(AC 26:02)

 

F Components

これです

F - Tree Patrolling

 

そのまま貼るというわけにはいかないのですがほぼ同じで、「各頂点を選んだか?」という情報を持ちながらDPしてあげればいいと思います

制約もO(N^2)を許す制約をしている(ちょっとこわいけど)ので、ほぼほぼ二乗の木DPだろうとなります

遷移は過去問ほどややこしくなく、もし1つでも子とつなぐなら連結成分が増えない、そうでなくてその頂点を選ぶなら増えるということを実装してあげればよいです

 

それなりにわかりやすく書けたと思います(ぼくの提出)

Submission #38403941 - UNIQUE VISION Programming Contest 2023 New Year (AtCoder Beginner Contest 287)

(AC 41:05)

 

G Balance Update Query

まず変更がないとして、処理の仕方を考えます

これは割と自明で、ソートしておいて大きい順からとればよいです

なので、ソートした形をなんとかして維持できるといいな~と思います

 

aiは大きいですが、出てくる種類数はN+Q以内であるため、クエリを先読みして座圧します

こうすると、各数字における個数を管理することでソート状態を保てます

では、クエリに高速に答えていきましょう

クエリ1,2:これは各数字における個数を更新すればよいです

クエリ3:ここが本番です、愚直にやると大きい順からたどるので各クエリに最悪N+Q回かかってしまいます

 

この問題を解消しましょう

必要なことは[i:N+Q]の和がx以上となる最大のiをみつけることです

これはセグメント木での二分探索を用いるとO(log(N+Q))で解けます

よって、クエリ3にも高速に答えることができ解けました

 

本番はセグ木への加算がバグって通らず...

(AC --:--)

 

総括

G通して勝てると思ったんだけどな

ABC285 参加記

たまにはと思って、Dから解いてみた

6完 59:19 + 1ペナで86位、こどふぉ勢がいないので順位は高いけど立ち回りがびみょい

A Edge Checker 2

ある程度慣れてる人ならAなんだけど、グラフ初見の人はたいへんそう

二分木なので親が子/2か?で判定できる

(AC 20:48)

 

B Longest Uncommon Prefix

SiがS[1~i]かと思ってあせるけど、そんなものBに出るわけないのでよくみるとS[i]だった

内容としては愚直にチェックすればOK

(AC 24:09)

 

C abc285_brutmhyhiizp

逆の操作はABC-Cで既出

26進法だと思って計算すればいい、

(AC 27:18)

 

D Change Username

ちょっと頑張ろうかなと思って早めに解いたけど、noimiさんが早すぎた

サンプルのダメな例みると、明らかに有向グラフがループしてるので、どうせ強連結成分があるかどうかだと思う

あとはACLのSCC使えばおわり

(AC 4:42)

 

E Work or Rest

ちょっと考察したけど、単純な形に帰着できていい気持ち

1つの平日の塊の長さをXとすると、その塊における生産性は簡単に計算できます(A[i/2]の和)

1つ平日の塊を追加するには、1つ休日を配置する必要があります

また、平日の塊のそれぞれの長さが決まって、休日を含めてN日以内におさまることがわかれば、それを満たす平日・休日の置き方は存在します(もしあまったら休日にすればいいです)

 

こう考えると、i日使うと生産性がPi得ることができるという条件がN個与えられ、sum(i) = Nとなるときの生産性を最大化する問題になります

これは重みi, 価値Piの個数制限なしナップサック問題だと考えられます

よって、dp[i][j] := 重みiまで考えて、現在の重みの総和がjのときの価値の最大値

と定義してdp[N][N]を求めればよいです

(AC 18:49)

 

F Substring of Sorted String

まず思うこととして、アルファベットが26文字しかないのでS[l:r]の中に「隣り合う文字が異なる箇所」が26個以上あれば必ず条件を満たしません

つまり、「隣り合う文字が異なる箇所」に着目すれば各クエリに対して26回以内のチェックで判定ができそうです

 

ということで、「隣り合う文字が異なる箇所」を管理することにしましょう

次に異なる場所がどこにあるか?が知りたい + クエリによって変化するのでsetで管理することにします

クエリ1は簡単で、両隣をみてあげて異なっているか更新すればよいです(同じになったらerase, 違ったらinsert)

 

クエリ2が本番になります

解説ではセグメント木を使っていますが、そうでない方法で書きます

まず、Sに含まれる各文字の個数を管理しておきます(vectorなどで管理して、クエリ1でも更新します)

次に、S[L:R]の中に各文字がどのくらいあるか調べましょう

 

Lを徐々に右に進めていく要領で確認できます(以下説明)

Lより右で最も近い「隣り合う文字が異なる箇所」をsetに対する二分探索で求めます

違う文字になる位置がyとすると、L-y個のS[L]が存在します

ここで、L = yに進め、同様の操作を繰り返します(この操作回数は文字の種類数で抑えられます)

このときにS[L] < S[y]である必要があり、そうでないならNoです

 

これでS[L:R]での各文字数がわかりました

あとは、足りていない文字が存在していないか確認すればよいです

S[L] ~ S[R]の間(S[L], S[R]は含まない)で、全体の文字数>S[L:R]中の文字数となる場所があればNo、そうでなければYesです

これで各クエリにO(σ logN)で答えることができてACとなります

(AC 59:19)

 

G Tatami

Hanjoじゃないんだな~

できる手法としてはDPかフローかなと思います

ただ、Hanjo 2でも Wがかなり小さい値だったので、これをDPでやるにはきついんだろうなと思います

フローかな?と思っていい性質を探すと(これはもっと早く気付くべきなんですが)、グリッドなので二部グラフであり、フローが使いやすそうだと思います

ざっくり考えると、1じゃない隣り合うマスに対して(i+jが偶数) -> (i+jが奇数)に辺をはって、最大流を解けばいいんですが、「ここには絶対流さないといけない!」というところがあります

「ここには絶対流さないといけない!」ところのコストを低くして、最小費用流にすればいいのでは?と思って書いたのですが、そういえば最小費用流はおおよそ流量×辺の数だけかかるので、TLEでした...

 

解説をみたんですが、最小流量制限つきってありましたね

勉強になります

(AC --:--)

 

総括

FでS[l:r] = T[l:r]だと思ってロスしたのかなしい

ABC283 参加記

G解かれすぎーーー、こまっちゃう

6完 64:05で202位、安定はしてる

A Power

std::powを使ったら、指数表記になってこわかったので普通にforでかけた

9 9でチェックしててよかった~

(AC 2:18)

 

B First Query Problem

い つ も の

さすがに無限回やったことある

(AC 4:41)

 

C Cash Register

ちょっと考察あるけど簡単~

今の位置から見て「00」なら2つ進めて、そうでなければ1つ進めるシミュレーション

(AC 7:00)

 

D Scope

問題文に「気を失う」って書いてあってなんだ??って思った

括弧列どこまでできるか?が重要なんだけど、どうせこういうのは括弧列の対応と相場が決まっているので、stackを使って括弧列の対応をだしておきます

あとは、各文字の最も右の位置をもっておいて、削除できるか判定しながらシミュレーションすればよいです

(AC 13:55)

 

E Don't Isolate Elements

まず、反転系の典型なんですが「順序は関係なくて、反転するなら1回でよい」です

で、ある行がちゃんと条件を満たしているかを確認するとしたら、i-1行目、i行目、i+1行目の反転状態がわかればよいです

dp[i][j][k] := i-1行目が反転しているかわかっていて(j = 0 / 1)、i行目が反転しているかわかっている(k = 0 / 1)ときにi行目が条件を満たすか?

という風にしたいのですが、i-1行目が反転しているかわかっていてi行目が反転しているかわかっているときに判断ができるのはi-1行目なので、

dp[i][j][k] := i-1行目が反転しているかわかっていて(j = 0 / 1)、i行目が反転しているかわかっている(k = 0 / 1)ときにi-1行目が条件を満たすか?

というDPを定義して計算していきます

 

条件を満たすかどうかは結構細かいところに考慮しないといけないので、関数にしておくとよいと思います

周囲を0,1以外の数でうめておくと端っこの処理が不要になり、ちょっと楽になります

(AC 44:33)

 

F Permutation Distance

| Pi - Pj | + | i - j |の最小化ですが、絶対値はかなりめんどくさいので外したいです

たとえば、Pi < Pjを固定してあげると、絶対値は1つ外せます

同様に考えると、(Pi, Pjの大小) × (i,jの大小)の4パターンしかないことがわかります

まあちょっとめんどくさいかもしれませんが、ほとんど同じなので4パターンすべて解けばいいです

 

たとえば、 Pi < Pj かつ i < jのときを考えてみましょう

最小化するべき値は Pj - Pi + j - iであり、-Pi - iはiを決めると固定されるので、Pj+jの最小化ができればよいです

Piをみるときには、それより値が大きなものがどこにあるかわからないといけないので、Piの大きい順に処理を行います

セグメント木を用いて、iの位置にPi+iをsetすることにします

そうすると、iより右にあるものについて最小値をとればPj+jの最小値をO(logN)で求められます

 

同様のことを残りの3パターンすべてについて考えて、その最小値をとればよいです

(AC 64:05)

 

G Partial Xor Enumertation

どうせ基底をとって、うまく小さい順に並べられればなと思って、noshi基底をとったんですが、小さい順に並びませんでした(ちーん)

(AC --:--)

 

総括

こういうE頭壊れるけど意外とパフォでる

ABC282 参加記

ポケモンでさぼっていたんですが、まともに復帰しました

6完 65:45で239位でした、まあまあ

A Generalized ABC

Aはfor文が定着したんですかね、逆に普通のifがきたらびっくりしそう

(AC 1:18)

 

B Let's Get a Perfect Score

よくあるBですが、or演算を使うことでループをちょっとだけ楽にできます

こういうのかっこいいんだけど、あんまり実用性は...

(AC 3:51)

 

C String Delimiter

エスケープシーケンスの練習?

"っていう文字はちょっとめんどうなので、エスケープシーケンスを使おうと思ったんですが、よくわかんなかったのでint型に文字を変更して解きました

やること自体はBにあってもおかしくなさそう

(AC 9:34)

 

D Make Bipartite 2

むずくないですか?D適正の人が二部グラフにどのくらい触れているのか...

まずそもそものグラフが二部グラフでないときはお話になりません、0で終わりです

そもそも二部グラフだった時について考えます

白・黒の2色で塗ることを考えると、つないだあとも二部グラフであるためには、白と黒の頂点を結ばなければいけません

逆にそうであれば、どのように結んでも問題ありません

よって、白の頂点の数をw, 黒の頂点の数をbとして、b*wが答えになります

...とすめばいいんですが、グラフが連結でない場合があります

 

連結でないものを結ぶ場合は、どのように結んでも問題がないので、各連結成分にある頂点の個数をKとして、K*(N-K)だけ増やすことができます

ただし重複ができるので省かないといけないことに注意しましょう

(AC 18:23)

 

E Choose Two and Eat One

これもむずいよ~

まず、N≦500なので各ペアにおける(x^y + y^x) mod Mは、繰り返し二乗法でO(N^2 log(N^2))で計算できます

そうすると、N*Nマスのグリッドから

・1つをのぞいた各行1つ選ぶ(そのときに消す)

・(i,j)を選ぶと、(j,i)は選べない

という条件で、スコアを最大化する問題に帰着されます

これは、「1つをのぞく」行を決め打ちして、フローを流せば燃やす埋めるで解ける気がします

...が、冷静になって考えるとEでフロー、しかもそれなりに考察しないといけないものがでるわけがないので、もう少し考えます

 

操作回数がN-1回になることと、ペアをつくることは頂点をつなぐことであるということを考えると、なんとなくグラフ構造が使えそうだなと思って、そこまでいくと最大全域木を構成するのがよさそうに思います

木構造になれば、操作列自体の構築も簡単(先に捨てるものから葉にすればよい)ので、これは適用できそうだと思います

ここまでくればあとは普通のMSTを書けばよいです

 

(AC 43:43)

 

F Union of Two Sets

構築+インタラクティブでおもしろそうだけど、むずかしそうだなと思いながら見ます

まずN=4000のときに何が飛んでくるかわからなくて、逆にここに全対応できればNがどんな値でもなんとかなることがわかります

どこから手を付けるかなんですが、絶対に必要なものから考えます

たとえば(5,5)と飛んできたときに長さ1のものがないと確実に死ぬので、長さ1の(1,1),(2,2)...(N,N)は必須になります

これがあると、長さ2には問題なく対応できます

となると、長さ3のものが必要です

長さ3があると、たとえば長さ5は1つだけ要素をかぶせることで3+3-1=5と構築できます

同様に考えると、長さnが全パターン網羅できればn*2までは網羅できます

そうすると、1,3,7,15...の長さのものを構築すればよく、これを実際に構築すると40000にいかないくらいになって制約的にも問題ありません

 

あとはクエリに答えていくんですが、クエリで与えられた長さをDとすると、1,3,7,15...を1つずつ調べて、D/2以上であればその長さのものを2つくっつけて構築できます

pairと番号の対応をmapで管理したので、クエリあたりの計算量O(logM^2)で解きました

(AC 65:45)

 

G Similar Permutation

挿入DPっぽいなーと思ったんですが、わからず...

復習します

(AC --:--)

 

総括

Eでハマっているようでは...