[白俊1965]箱に入れる🧠✨

5845 ワード

🥚質問する


https://www.acmicpc.net/problem/1965
  • 動的プログラミング

  • 🥚入力/出力



    🍳コード#コード#


    import sys
    import bisect
    input = sys.stdin.readline
    
    n = int(input())
    arr = [0] + list(map(int, input().split()))
    
    # LIS = O(NlogN)
    # dp[i] = 길이가 i인 증가하는 부분 수열의 마지막 숫자의 최소값
    
    def LIS():
        dp = [0]
        for i in range(1, n+1):
            if arr[i] > dp[-1]:
                dp.append(arr[i])
            else:
                idx = bisect.bisect_left(dp, arr[i])  # 이분탐색으로 들어갈 자리 찾기
                dp[idx] = arr[i]
        return len(dp) - 1
    
    ans = LIS()
    print(ans)

    🧂アイデア


    DP, LIS

  • の最長増分部分数列のアルゴリズムを用いて解いた.
    以前は何度か関連問題を解いたが,O(Nlogn)時間の複雑さを持つアルゴリズムを実現する上では誤りがあるようだ.今日解いたとき突然...これじゃないの?考えて修正しました.
  • dp[i]=長さiの増分部分数列に最後の数字の最小値を格納する.

  • 格納ボックスサイズのリストarrを巡回する場合、arr[i]がdpの最後の値より大きい場合、dpにarr[i]を追加します.

  • arr[i]がdpの最後の値より小さい場合、arr[i]に含まれる可能性のあるインデックスを二分的に検索し、dp[idx]=arr[i]に更新します.
  • 二分探索Python対分モジュールを用いた対分left関数.
    このN個の入力に対して二分検索を実行するので、時間の複雑さはO(Nlogn)です!
  • 注1:LISコードと説明
    注2:最長の2進数列
    注3:最も長い減少部分数列
    注4:最大増分4