<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      線性DP

      很多問題往往會給出一個序列或者一個數表,讓你對其進行劃分,或者選出其中的某個最優子集。這一類問題往往適合使用線性DP。
      線性DP是一種非常常見的DP。它往往以狀態內的其中一個維度劃分階段。接下來,我將給出幾個非常重要的轉移方程。

      最長上升(下降)子序列LIS

      已知一個序列\(A_i\)。現在我希望從這個序列中從左往右選出若干個元素,使得這些元素組成的子序列元素大小單調遞增。求這樣序列的最大長度。

      我們嘗試設計狀態表示這個最大高度。不難發現,只要\(A_i < A_j,i<j\)\(A_j\)就可以和\(A_i\)合并。這個過程和\(A_i\)以前的元素沒有直接的關系。
      于是我們嘗試設\(F(i)\)為以\(A_i\)為結尾的,從\(A_1 \sim A_i\)中選出的LIS。不難發現這樣一個轉移關系:

      \[ F(i) = \max_{j < i, A_j < A_i}\{F(j)\} + 1 \]

      也就是說,我們以前\(i\)個序列劃分階段,如果有\(A_j < A_i, j < i\),那么答案就可以從\(F(j)\)轉移到\(F(i)\)
      初始值\(F(1) = 1\)

      上面這個做法的時間復雜度為\(O(N^2)\),但我們可以通過以下兩種方式做到\(O(N \log N)\)

      樹狀數組維護最大值
      樹狀數組不能維護區間最大值,但可以維護前綴和后綴最大值。一個狀態\(F(i)\)的決策集合為\(\{j\mid j < i, A_j < A_i\}\)。我們可以在\(A_i\)的值域上建立樹狀數組,保存結尾在\([0,A_i]\)范圍內的最長上升子序列長度。由于我們每次按輸入順序查詢,并更新之,我們自動滿足了\(i < j\)的條件。

      貪心+二分
      并不能算是標準做法,但是非常巧妙。它并沒有直接設狀態表示最長上升子序列的長度,而是設\(F(i)\)表示當最長上升子序列的長度為\(i\)時,這個子序列末尾的最小值。
      有一個比較顯然的貪心策略:當兩個上升子序列長度一樣時,我們應該保留結尾較小者,因為它更有可能接納更長的上升組序列。
      核心代碼:

      inline int bs(int num)
      {
          int l = 0, r = maxlen + 1;
          while(l < r)
          {
      	int mid = (l + r) >> 1;
      	if(F[mid] > num)
      	    r = mid;
      	else
      	    l = mid + 1;
          }
          return l;
      }
      int main()
      {
          N = qr(1);
          RP(i, 1, N) A[i] = qr(1);
      
          RP(i, 1, N)
          {
      	int pos = bs(A[i]);
      	if(pos > maxlen)
      	{
      	    maxlen = pos;
      	    F[pos] = A[i];
      	}
      	else
      	    F[pos] = A[i];
          }
          printf("%d", maxlen);
          return 0;
      }
      

      可以看出,盡管DP的速度相較搜索而言相當快了,但也可以通過其他算法進行更深層的優化。

      最長公共子序列LCS

      給定兩個序列\(A_i\)\(B_i\),現在我們要求找出一個序列\(C\),使得\(C\)既是\(A\)的子序列,又是\(B\)的子序列。請你最大化序列\(C\)長度。

      從上一題來看,一個比較直觀的想法是設\(F(i,j)\)表示以\(A_i\)結尾,以\(B_j\)結尾的最長公共子序列。當\(A_i \neq B_j\)時,直接令\(F(i,j)=0\)。當\(A_i = B_j\)時,有轉移方程 \(F(i,j) = \max_{k < i, l < j, A_k = A_i, B_l = B_j}\{F(k,l)\}+1\)

      這個方程有兩個比較明顯的問題。首先,\(F(i,j)\)這個狀態是不是過度冗余?很大一部分的\(F(i,j)=0\),這樣會浪費大量的空間。其次,時間復雜度過高,達到了\(O(N^4)\)。如果用鏈表也許可以減少時間,但還是減少不了多少。

      考慮這樣一種做法:設\(F(i,j)\)表示前綴序列\(A_{1\cdots i}\)\(B_{1\cdots j}\)的最長個公共子序列之長(此時這個子序列不一定包含\(A_i,B_j\)!)。此時的\(i,j\)可以看作是兩個掃描數組的指針。

      \(i,j\)想向后擴展時,有以下情況:

      • \(A_{i+1}=B_{j+1}\)。此時\(i,j\)均往后跳一位,并讓序列的長度\(+1\)
      • \(A_{i+1}\neq B_{j+1}\)。此時指針是不能同時跳的。根據DFS的思想,我們會作如下嘗試:
        • 嘗試讓\(i\)往后跳一次,搜索\((i+1,j)\)這個狀態
        • 嘗試讓\(j\)往后跳一次,搜索\((i,j+1)\)這個狀態
        • 返回兩次嘗試的最大值

      綜上,當\(A_{i+1}=B_{i+1}\)時,\(F(i,j)\)可以直接轉移到\(F(i+1,j+1)\),并增加一個貢獻。反之,\(F(i,j)\)應該轉移到\(F(i,j+1)\)或者\(F(i+1,j)\),并取其中的最大值。

      把上面的每個方程反過來寫,寫成被轉移狀態關于轉移狀態的表達式,把\(i+1,i\)改成\(i,i-1\),就可以得到轉移方程:

      \[ F(i,j) = \begin{cases} F(i-1,j-1)+1 & A_i = B_j\\ \max\{F(i-1,j),F(i,j-1)\} & A_i \neq B_j \end{cases} \]

      另外,這道題的階段劃分依據叫做“已經處理的前綴長度”。這里并沒有直接指明到底是哪一個前綴,因此任意選擇一個序列即可。

      最長公共上升子序列LCIS

      LIS和LCS的結合。求序列\(A_i,B_i\)最長的,單調遞增的LCS。

      注意到第一題的狀態保證了“取結尾”,而第二題卻沒有。為了降低時間復雜度,這里我們應該采用“半保留”的設計方法。
      \(F(i,j)\)表示掃描到前綴子序列\(A_{1\cdots i}\),以\(B_j\)結尾的LCIS。

      \(i\)指針向后移一位時,前綴子串會多出來一個新的數\(A_{i+1}\)。對于這個數,我們有兩種方案:

      • 不嘗試匹配這個數。此時\(j\)不動,直接把答案轉移給\(F(i+1,j)\)
      • 嘗試匹配這個數。此時\(j\)往后跳,找到一個位置\(k\),使得\(B_k = A_{i+1}, B_j < B_k\)。嘗試更新這個狀態\(F(i+1,k)\)。注意到可能有多個數匹配到這個位置\(k\),因此不能直接賦值。

      把這兩種方案寫成填表法的形式,把上面的\(j\)分別替換成\(j-1\)\(k\),就得到:

      \[F(i,j) = \begin{cases} F(i-1,j) & A_i \neq B_j\\ \max_{k < j, B_k < B_j}\{F(i-1,k)\} + 1 & A_i = B_j \end{cases} \]

      這個轉移的時間復雜度是\(O(N^3)\)的,其中這里只能以\(A_i\)的前綴子序列長度劃分階段。但它還有優化的空間。

      注意到在任意時刻,如果我們需要\(O(N)\)枚舉\(F(i,j)\)的決策集合,那么必然有\(A_i = B_j\)。因此,當\(A_i = B_j\)時,轉移方程還可以寫成這個樣子:

      \[ F(i,j) = \max_{k < j, B_k < A_i}\{F(i-1,k)\}+1 \]

      在每個階段,\(A_i\)的值都是固定的;在當前階段,對決策集合的限制條件只有\(k < j\)。因此,當前\(F(i,j)\)計算完之后,\(j < j' = j+\Delta j\),那么\(F(i,j)\)就會立刻被加到\(F(i,j')\)的決策集合中!
      這就是時間復雜度過大的根源。我們花費了額外\(O(N^2)\)的時間來重復掃描這個決策集合,而這個集合實際上是“開源”的,可以供當前階段的所有狀態使用。
      因此,我們只需要用一個變量\(F_m\)來維護\(\max_{B_j < A_i}\{F(i,j)\}\)。每當計算完一個狀態\(F(i,j)\),我們就可以拿它來更新\(F_m\)。這樣時間復雜度就降為了\(O(N^2)\)

      posted @ 2019-09-26 10:58  LinearODE  閱讀(653)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品揄拍一区二区久久| 中文字幕人妻在线精品| 亚洲人成人网站色www| 干老熟女干老穴干老女人| 国产人妻高清国产拍精品| 亚洲AV片一区二区三区| 少妇人妻互换不带套| 日韩一区二区三区高清视频| 国内不卡不区二区三区| 中文字幕日韩精品有码| 蜜臀av久久国产午夜| 国产成人精品1024免费下载| 亚洲av无码精品蜜桃| 亚洲熟女乱综合一区二区| 一区二区三区四区五区自拍| 日韩深夜福利视频在线观看| 国产特级毛片AAAAAA视频| 盐池县| 毛葺葺老太做受视频| 日韩有码中文字幕第一页| 亚洲av本道一区二区| 国产偷国产偷亚洲清高网站| 人妻少妇一区二区三区| 国产亚洲精品视频一二区| 草草浮力影院| 蜜桃av亚洲精品一区二区| 精品一二三四区在线观看| 久久天天躁夜夜躁狠狠85| 亚洲精品国产美女久久久| 国产精品乱人伦一区二区| 国产91小视频在线观看| 国产无遮挡免费真人视频在线观看| 久久精品国产九一九九九| 日本亚洲色大成网站www久久| 亚洲开心婷婷中文字幕| 男人的天堂av社区在线| 欧美18videosex性欧美tube1080| 999精品色在线播放| 2021国产精品视频网站| 久久国产精品波多野结衣| 欧美人与禽2o2o性论交|