TopCoderのレートはあまり気にしていないつもりだったけど、緑に落ちたのは結構ショックだったので、もっと真剣にやらないと、と反省しました。
それに、このEasyは通さなくてはいけない問題だったので、そこも反省。
Div1 Easy ArraySorting
数列Aの要素をいくつか変更し、Aを広義単調増加にしたい。
変更する要素の個数が最小になるようにし、辞書順最小のAを求める。
まあ、LISを復元する問題といって良いと思う。
LISに関する理解がちゃんとしていれば解けたはずなので、解けなかったのはLISの理解ができていなかったということでしょう。
「辞書順最小」というのに惑わされるけど、「DP[i]で、長さiのLISの最終要素の最小値」を取る、という方法(たとえば、ここの説明が分かりやすいと思う)でLISを求める際に、復元用のリストを用意していれば、自然と辞書順最小のものが求められる。
この問題も、yukicoder contest 237のNo.992 最長増加部分列の数え上げも、それほど捻った出題じゃないのに意外と難しく感じてしまうのは、LISのアルゴリズム自体がそもそも簡単じゃないからだと思う。
とはいえ、基本的なアルゴリズムなのだから、ちゃんと身に着けておかないと……。
以下、ACコード。
import bisect class ArraySorting(): def arraySort(self, A): N=len(A) DP=[1<<31]*N fr=[-1]*N # 復元用のリスト for i in range(N): a=A[i] pos=bisect.bisect_right(DP,a) DP[pos]=a if DP[pos-1]==1<<31: fr[i]=1 else: fr[i]=DP[pos-1] ANS=0 # LISの長さ for i in range(N): if DP[i]!=1<<31: ANS=i LASTV=DP[i] NEXT=LASTV B=[] for i in range(N-1,-1,-1): a=A[i] if a==NEXT: B.append(a) NEXT=fr[i] else: B.append(NEXT) return B[::-1]
0 件のコメント:
コメントを投稿