2021年7月18日日曜日

第七回 アルゴリズム実技検定

辛うじて全完したが、最後の問題の正しい解法がわからなかった。

K - 急ぎ旅

最短経路DAGを作ってからDPした。

ダイクストラと同時にできるらしい。確かに。

L - たくさんの最小値

最小値の列挙は遅延セグメント木上を二分探索すればできる。いつもこの方針でやっていて、想定解のようにノードに持たせる情報を増やすやり方でやったことがない。後者でないと難しい設問ってあるんだろうか。

M - 分割

明らかに最小費用流だと思ったが、グラフの作り方で長時間かけてしまった。

辺の下限流量を決めて変形するイメージで作った。まず、整数AiA_iを表す各位置iiiin,iouti_{\mathrm{in}}, i_{\mathrm{out}}に分割する。

  • SSからiouti_{\mathrm{out}}に容量1、コスト0の辺を張る
  • iini_{\mathrm{in}}からTTに容量1、コスト0の辺を張る
  • iouti_{\mathrm{out}}からTTに容量1、コストCCの辺を張る
  • i<ji < jであるすべてのjjについて、iouti_{\mathrm{out}}からjinj_{\mathrm{in}}に容量1、コストAiAj|A_i-A_j|の辺を張る

想定解は「通ってほしい辺」のコストを-\inftyにしてから変形する考え方のようだった。こちらは全然考えたことがなかった。

N - モノクロデザイン

JOI 2012 春合宿 - fortune_telling

O - コンピュータ

(Bi)(B_i)が狭義単調増加の場合が解ければよい。また、世界にはB1,...,BNB_1, ..., B_N円のコンピュータしか存在しないとしてよい。

dp[x]=x\operatorname{dp}[x] = x日目でちょうどコンピュータを買い替えなければならない場合の最大所持金額

とする。xx日目に買えるコンピュータは、所持金以下であるような最大価格のコンピュータをrrとしてBx,Bx+1,...,BrB_x, B_{x+1},..., B_rのいずれかであり、ByB_yを買うとすると遷移はdp[y+1]:=max(dp[y+1],dp[x]+Ax+1+Ax+2+...+Ay+1By)\operatorname{dp}[y+1] := \max(\operatorname{dp}[y+1],\operatorname{dp}[x]+A_{x+1}+A_{x+2}+...+A_{y+1}-B_y)Ax+1+Ax+2+...+Ay+1A_{x+1}+A_{x+2}+...+A_{y+1}の部分を累積和で計算すると、このDPはO(N2){O}(N^2)である。

o(N2)o(N^2)にする方法がわからなかった。試しに、買うコンピュータをxxrrだけにしたものを投げると半分以上は通る。それならと思って両端から2000個程度(x,x+1,...,x+2000x, x+1, ..., x+2000k2000,...,k1,kk-2000, ..., k-1, k)の遷移に限定してみたらACした。

解説を見た。

dp[x]=\operatorname{dp}[x] = コンピュータxxを買った時点での支出の最小値

とする。コンピュータppを買ってから次に買うコンピュータとしてxxを選べる必要十分条件はA1+...+Ap+1dp[p]BxA_1+...+A_{p+1}-\operatorname{dp}[p] \ge B_xであること。これが成り立つようなppについて、dp[x]:=minpdp[p]+Bx\operatorname{dp}[x] := \min_p\operatorname{dp}[p] + B_xと更新すればよい。

実装としては、range minを載せた平衡二分木のキーA1+...+Ap+1dp[p]A_1+...+A_{p+1}-\operatorname{dp}[p]に値dp[p]\operatorname{dp}[p]を対応させておけば、キーがBxB_x以上のノードについてのdp[p]\operatorname{dp}[p]の最小値を高速に求められる。


Oは今までのPASTで一番難しく感じた。