🙆

AtCoder Beginner Contest ABC403 解法メモ

に公開

文中で使用しているのは、PythonライクでAtCoderに最適な言語の1つNimです

ABC403

ABC403A - Odd Position Sum

解法

(0..<N).toSeq.filterIt(it mod 2==0).mapIt(A[it]).sumでよい
ACコード

ABC403B - Four Hidden

解法

0..T.len-U.lenのiで、
(0..<U.len).toSeq.allIt(T[i+it]==U[it] or T[i+it]=='?')が成立するかみればよい
ACコード

ABC403C - 403 Forbidden

解法

各ユーザー毎に、

  • クエリ1で閲覧権限を与えられたコンテストページの番号を格納するHashSet
  • クエリ2で閲覧権限を与えられたかのbool

を保持し、
クエリ3が来たら、
HashSetにその番号があるか、そもそも、全ページの閲覧権限があるか
を確認すればよい
ACコード

ABC403D - Forbidden Difference

解法

Aiの出現回数をカウントする配列を用意して、
それを間隔Dで抜き出したとき、
数字が並ばないように削除することを考える
これは0~10^6の配列位置をmod Dで分類した配列毎に考えればよく、
各々の配列に対し、その項を削除するかどうかのDPを行えばよい
dp[数列のi項目]=そこまでで削除することになった個数の合計
とすると、
d[i]=min(iの個数を0にした場合のそこまでの最小値,i-1の個数を0にした場合のそこまでの最小値)
0にする、というのは、そもそも0かそうでなければ、その個数削除する、という意味)
となる
実装としては、
単にc=A.toCountTableとして、
また、n=10^6 div Dとして、
for i in 0..<D:
 for j in 0..n:
の中で、n+1項の配列dpに対して、
d[j]=min(dp[j-1]+c[D*j+i],dp[j-2]+c[D*(j-1)+i])
を遷移させていけばよい
答えは、各iでのdp[n]を足し合わせたものになる
ただし、D=0の場合は、各種1つだけ残ればよいから、答えはN-c.lenとなる
ACコード

メモ

D=0の場合を別に考えねばならないことが、最後までわからなかった
当初、1つ置きに削除すればよいと誤認した
AのCountTableのkeysから、
間隔Dの連続した数列を可能な限り抜き出し、
各々の中で連続しないように削除していくことを考え、
Ai0~10^6なので、頂点10^6+1個のUnion-Findを用意し、
Aiに対して、Ai-DAi+DA内にあれば辺を張る、としていくことで、数列群を作り、
できたgroupsの各々をソートした数列に対し、
「削除しないで残すこと」が2連続で起こらないよう、合計削除個数を最小化することを考え、
DPで、
dp[数列のi項目][その項を削除したか(1)しないか(0)]=そこまでで削除することになった個数合計
として、
dp[i][0]=dp[i-1][1]
dp[i][1]=dp[i-1].min+(i項目の個数)
の遷移を進め、
全groups数列のdp[^1].minの合計を求めた

ABC403E - Forbidden Prefix

解法

入力をすべて先読みし、
Xiのハッシュ値から、何番目のクエリかが引ける連想配列(同じXiに対しては。最も早いもの)を用意
答えとなる数列aに対して、
Yiが出現したクエリ位置で+1
Yiローリングハッシュして、連想配列を引きながら、一致した一番早いクエリ位置で-1
していく
最後、a累積和を取ったものが答え
ACコード


反復学習にはmochiがおすすめ
全問入ったdeckはこちら

Discussion