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 件のコメント:
コメントを投稿