高程昱
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    --- tags: Training type: slide --- <style> .reveal .slides { text-align: left; font-size:30px } </style> # DP optimization Introduction to Competitive Programming 2022/05/25 ---- - DP with Data Structure - 單調隊列優化 - 最大子矩陣 - nearest greater element --- ## DP with Data Structure Longest Increasing Subsequence 給你一個長度為 $N$ $(1 \le N \le 10^5)$ 的整數序列 $a$, 求出最長的子序列其元素為非嚴格遞增 ---- ## DP 轉移式 `dp[i]` 為以第 $i$ 個元素為結尾的最佳解 轉移由前面某個元素 `a[j]` 為結尾且 `a[j]` $\le$ `a[i]` `dp[i] = max(dp[j]) + 1` ; \( `j < i` $\land$ `a[j]` $\le$ `a[i]`) 複雜度 $O(N^2)$ ---- `dp[i] = max(dp[j]) + 1` ; \( `j < i` $\land$ `a[j]` $\le$ `a[i]`) 要求以上轉移式,等價於求所有 $\le$ `a[i]` 的元素中,最大的 dp 值 可以用線段樹維護,線段樹儲存的為所有出現過的值 以序列 [1, 3, 2, 4, 3] 為例 可以算出分別的 dp 值為 [1, 2, 2, 3, 3] ![](https://i.imgur.com/UwoR6xX.png =300x) 最底層的元素為到目前為止 分別以數字 1, 2, 3, 4 為結尾的元素中最大的 DP 值 ---- 計算 DP 從第一個元素開始,一開始線段樹每個值都設為 0 每次算 DP[i] 等於前面所有小於自己的元素中最大的 DP 值 直接 query 線段樹小於等於自己的區間的最大值即可 ```cpp dp[i] = segTree.query(0, lower_bound(ind.begin(),ind.end(),a[i]))-ind.begin()) + 1; ``` 原本需要迴圈跑過全部小於自己的所有元素 DP 值, 現在只需要區間詢問最大值+1 即為 dp[i] 複雜度 $O(NlgN)$ ---- ### 單調隊列優化 例題 [相隔小於一定距離最小總和子序列](https://zerojudge.tw/ShowProblem?problemid=c528) 給定一個長度為 $N$ 的整數序列及一個正整數 $K$, 請蓋掉任意個數字使得原序列中任意的連續 $K$ 個數字都至少有一個數字被蓋掉了,請問蓋掉的數字的總和最小為多少? ---- 給定一個長度為 $N$ 的整數序列及一個正整數 $K$, 請蓋掉任意個數字使得原序列中任意的連續 $K$ 個數字都至少有一個數字被蓋掉了,請問蓋掉的數字的總和最小為多少? ### 轉移式 `dp[i]` 定義為 以第 `i` 個結尾,並且蓋掉第 `i` 個元素的最佳解 `dp[i] = min(arr[i] + dp[j]) ,i-k` $\le$ `j` $<$ `i` ---- 注意題目 $N, K$ 大小 $K \le N \le 10^6$ 直接做 $\to 10^{12}$ TLE ```cpp= for(int i=0;i<n;i++){ //TLE dp[i] = (i<k?arr[i]:INF); for(int j=i-1;j>=max(i-k,0);j--){ dp[i] = min(dp[i],dp[j] + arr[i]); } } ``` ---- ### 優化? ```cpp= for(int i=0;i<n;i++){ //TLE dp[i] = (i<k?arr[i]:INF); for(int j=i-1;j>=max(i-k,0);j--){ dp[i] = min(dp[i],dp[j] + arr[i]); } } ``` 看上面程式碼會發現 3~5行求的就是區間 [i-k,i-1] 之間的最小值 因此可以用線段樹優化,找區間最小值 ```cpp= for(int i=0;i<n;i++){ mn = (i<k?arr[i]:INF); mn = min(mn,segTree.query(max(i-k,0),i-1)); segTree.update(i,mn); } ``` 複雜度 $O(NlgN)$ ---- 而線段樹實作複雜度很高, 實際上可以用 STL priority_queue 儲存 每次放進去 pair(dp[i], i); 每次取 priority_queue 最小的 dp 值, 而如果最小值過期則直接 pop 掉 --- ### 單調隊列 會發現我們在求第 $i$ 項的dp值時 只需要保留 $[i-k,i-1]$ 的 dp 值就好,更前面的完全用不到 並且對於所有(i, j) 如果 dp[i] $\ge$ dp[j] $\land$ i < j 只需要保留 dp[j] 即可, dp[i] 不可能更新最小值 所以最後剩下的 DP 值都會符合 如果 i < j 則 dp[i] < dp[j] 而可以用 deque 儲存這些元素 ---- ### deque STL 資料結構,每次可以 $O(1)$ 從 front, end 新增刪除元素 因此 每次算出第 i 項的 dp 值放進 deque 前 裡面的比 dp[i] 大的值都可以 pop 掉,只需保留比他小的 dp 值就好 並且如果裡面有值過期(index < i-k),則也將他刪除 deque 裡面的元素最後只會單調遞增 $dp[i]<dp[j] \ \forall \ i<j$ ---- ### 例子 n = 9, k = 3 8 3 6 5 7 -5 1 8 5 ---- ### 範例 ```cpp= deque<pair<int,int>> dq; //index, value int calc(){} for(int i=0;i<n;i++){ // dp 求最大值 while(!dq.empty() && dq.front().first < i-k) dq.pop_front(); //判斷dq裡的東西有沒有過期 dp[i] = calc(); while(!dq.empty() && dq.back().second >= dp[i]) dq.pop_back(); //判斷dq裡的東西是不是比當前dp[i]小,如果比較小就去掉 dq.push_back(make_pair(i,dp[i])); } //保證dq從左至右value由大到小 ``` ---- ### 複雜度 $O(N)$ --- ## 最大矩形面積 <div style="font-size: 30px"> 題目給你 $N \times M ( N, M \le 2000)$ 的矩陣,上面有一些格子有障礙物, 要找出一個子矩陣,沒有任何障礙物。 問你所有合法的子矩陣中,最大面積為多少? ![](https://i.imgur.com/UKFciNm.png) 以上圖為例,假設黑色為障礙物,則合法中最大的子矩陣為紅色框起來的,面積為6 </div> ---- ## 想法1 <div style="font-size: 30px"> 暴力窮舉所有矩陣判斷合不合法 $O(N^6)$ * 窮舉左上角 $O(N^2)$ * 窮舉右下角 $O(N^2)$ * 窮舉矩陣內的每一格判斷是否有障礙物 $O(N^2)$ </div> ---- ## 想法2 <div style="font-size: 30px"> * 窮舉左上角 $O(N^2)$ * 窮舉右下角 $O(N^2)$ * ~~窮舉矩陣內的每一格判斷是否有障礙物 $O(N^2)$~~ 計算前綴和,左上到每個點為右下的矩形裡面的障礙物數量 ![](https://i.imgur.com/ERdxJhx.png) 如果要計算區間內的障礙物數量,用排容原理 假設要求 [2,2] 到 [3,4] 子矩陣的障礙物數量 則為 prefix[3][4] - prefix[3][1] - prefix[1][4] + prefix[1][1] </div> ---- * 窮舉左上角 $O(N^2)$ * 窮舉右下角 $O(N^2)$ 複雜度 $O(N^4)$ 此作法複雜度足夠快去解昨天 [CPE 第五題](https://onlinejudge.org/external/1/108.pdf) ---- ## 想法3 ### DP 先 $O(N^2)$ 計算出每格往上最高可以到多高 ![](https://i.imgur.com/SK23MaS.png) 之後窮舉以每格為右下角的所有可能矩形 每次往左判斷從起始格到當前往上最高可以多高 以 [3,4] 為例 往左 1 格高度最高可以為 2 往左 2 格高度最高可以為 2 往左 3 格高度最高可以為 1 ---- * 窮舉右下角 $O(N^2)$ * 窮舉左界 $O(N)$ 複雜度 $O(N^3)$ 但...還不夠 $N^3 = 8 \cdot 10^9 \to TLE$ ---- ## O($N^2$) 做法 先 DP 每格往上有幾格可以用 一樣窮舉以每個點當右下 對於每一個 row 變成轉換為以下問題 [ZJ c907](https://zerojudge.tw/ShowProblem?problemid=c907) 現有 N 個寬度為1單位的長條圖(例如下圖所示),試求此長條圖中可以形成的最大矩形面積。 ![](https://i.imgur.com/kUmzTaM.png =300x) ---- ## 作法 使用 stack 維護遞增子序列 stack 裡儲存:從 index $i$ 開始,可以放的最高高度為 $h$ [2, 5, 7, 4, 5] ![](https://i.imgur.com/svsn4qA.png =250x) 前三個長度為遞增的,因此可以直接放進 stack 裡面 stack: [(1, 2), (2, 5), (3, 7)] ---- ![](https://i.imgur.com/svsn4qA.png =250x) 到前 3 個為止 stack 裡的都是合法的 從 index 1 開始到目前第 3 個為止可以放的矩形最高高度為 2 從 index 2 開始到目前第 3 個為止可以放的矩形最高高度為 5 從 index 3 開始到目前第 3 個為止可以放的矩形最高高度為 7 而第 4 個高度為 4,如果直接放進去 stack 會破壞維護的性質 因此所有高度比他高的都要 pop 掉 而 pop 掉的時候順便更新答案 ---- ## pop 更新答案 ![](https://i.imgur.com/H0B7bYv.png =250x) stack: [(1, 2), (2, 5), (3, 7)] 當前為 (4, 4) 因此要 pop 掉 (2, 5), (3, 7) 也就是 index 2 開始高度 5 只能到 index 3 index 3 開始高度 7 只能到 index 3 分別用以上兩種高度 $\times$ 寬度更新答案(最大面積) (3-2+1)*5, (3-3+1)*7 ---- ![](https://i.imgur.com/sijCLqp.png =250x) 更新完後即可把當前高度放進 stack 裡面 原本要放進去為 (4, 4) 從 index 4 開始到目前為止可以放的矩形最高高度為 4 但會發現 pop 掉的位置高度都 $\ge$ 當前高度 因此放進去的為 pop 掉的所有位置最前面那個 為 (2, 4) 從 index 2 開始到目前為止可以放的矩形最高高度為 4 ---- ![](https://i.imgur.com/UYsSpYw.png =250x) 做完後 stack 裡會有 [(1, 2), (2, 4), (5,5)] 為遞增子序列分別為從 從 index 1 開始到最後可以放的矩形最高高度為 2 從 index 2 開始到最後可以放的矩形最高高度為 4 從 index 5 開始到最後可以放的矩形最高高度為 5 而也可以用這些去更新答案(最大面積) (5-1+1)*2, (5-2+1)*2, (5-5+1)*5 ---- ## 複雜度 從左往右掃描過去 每個高度會被放到 stack 一次,最多也只會 pop 出來一次 複雜度為 $O(M)$ 而如果是要求最大子矩形的面積總共有 N 行 每行做一次複雜度為 $O(NM)$ --- ## nearest greater element 給你一個長度為 $N$ $(1 \le N \le 10^6)$ 的正整數序列 $a$ 對於每個數字,求出往左跟往右第一個大於他的數字, 如果找不到就輸出 -1 sample input ``` 5 4 2 1 7 3 ``` sample output ``` -1 7 4 7 2 7 -1 -1 7 -1 ``` ---- 暴力可以 O($N^2$) 每個數字往左或往右找 或者維護一顆 取max的線段樹從當前位置找下去, 遞迴時 greedy 選盡量靠近的位置 複雜度 O(NlgN) ---- 用 stack 做 類似求最大子矩陣作法 往左跟往右各做一次 分別維護一個遞減序列 從第一個元素開始 push 進去 如果 stack 的 top $\le$ 當前元素則 pop 掉 直到 stack 變空的或 top 比當前元素大為止 ---- a = [4, 2, 1, 7, 3] 第 1 個元素: stack 是空的左邊沒有比他大的值 接著放進 stack 裡, stack = [4] 第 2 個元素: stack 的 top 為 4 比當前元素大, 紀錄答案並放進 stack 裡, stack = [4, 2] 第 3 個元素: stack 的 top 為 2 比當前元素大, 紀錄答案並放進 stack 裡, stack = [4, 2, 1] 第 4 個元素: stack 的 top 為 1, 比當前元素小 pop 到空或者當前元素大為止 接著放進 stack 裡, stack = [7] 第五個元素: stack 的 top 為 7, 比當前元素大, 紀錄答案並放進 stack 裡 ---- 複雜度 $O(N)$ --- ### Question Time and Practice [Homework Link](https://vjudge.net/contest/497108) 提交期限到下星期三 6/1 23:59 截止

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully