Skip to content

Instantly share code, notes, and snippets.

@ia7ck
Last active January 3, 2018 04:13
Show Gist options
  • Save ia7ck/61fac29d4690c3216fa9cb726caba250 to your computer and use it in GitHub Desktop.
Save ia7ck/61fac29d4690c3216fa9cb726caba250 to your computer and use it in GitHub Desktop.

https://twitter.com/yfba_/status/948287028415770624

問題1

増加列(Judge ver.)

概要

(1, 2, ..., n)の順列pが与えられる。pの広義増加部分列の個数はいくつか。

方針

dp[i]:=the number of increasing subsequence which ends with i-th element とする。遷移はdp[i]=sum(dp[j])+1。ただし、和はj<iかつp[j]≦p[i]なる全てのjに対して取る。求めるものはsum(dp[0, n))。O(n^2)なのでn≦100なら間に合う。

問題2

増加列(Contestant ver.)

概要

f(p[])=n=前の問題で求めた答え が与えられるので、具体的なpの例を1つ示せ。ただしp.length≦200を満たすように構成せよ。

方針

p=1, 2, ..., kのとき、dp[i]=2^iとなるのでi=0, 1, ..., k-1について和を取るとf(p[])=2^k-1。nを超えないような最大のkを取ってきて、1, 2, ..., kに要素をいくつか挿入していって新しくr=n-(2^k-1)個の増加部分列が生えるようにしよう。

p=1, 2, ..., kのi番目 (0-indexed) の要素の直前にk+1を挿入することを考えると、k+1を末尾とする増加部分列の個数はsum(dp[0, i))+1=2^i。末尾以外にk+1を含む部分列が増加列になることはないから、k+1の挿入でf(p[])はちょうど2^i増える。なのでrの立ってるbitを1つずつ折っていく感じで、rの(2進表記での)桁数回だけpに挿入すればいい。このことから、p.lengthの制約も満たせると分かる。

ただし、複数個挿入するときは前のほうに大きな要素を挿入しないといけない。これは、たとえばk+1, k+2を挿入したことによって{k+1, k+2}という増加部分列が新しく生えてしまうと変な感じになるため。

感想

Judge ver.はLISのdpを知ってると難易度が下がるかも。LISと同様にsegtreeを使ってO(nlogn)に落とせる。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment