最長上公升子串行O nlogn

2021-09-01 07:42:57 字數 1142 閱讀 8802

最近在做單調佇列,發現了最長上公升子串行o(nlogn)的求法也有利用單調佇列的思想。

最長遞增子串行問題:在一列數中尋找一些數,這些數滿足:任意兩個數a[i]和a[j],若i

設dp[i]表示以i為結尾的最長遞增子串行的長度,則狀態轉移方程為:

dp[i] = max, 1<=j

這樣簡單的複雜度為o(n^2),其實還有更好的方法。

考慮兩個數a[x]和a[y],x

按dp[t]=k來分類,只需保留dp[t]=k的所有a[t]中的最小值,設d[k]記錄這個值,d[k]=min。

這時注意到d的兩個特點(重要):

1.d[k]在計算過程中單調不公升;           

2.d陣列是有序的,d[1]

利用這兩個性質,可以很方便的求解:

1. 設當前已求出的最長上公升子串行的長度為len(初始時為1),每次讀入乙個新元素x:

2. 若x>d[len],則直接加入到d的末尾,且len++;(利用性質2)

否則,在d中二分查詢,找到第乙個比x小的數d[k],並d[k+1]=x,在這裡x<=d[k+1]一定成立(性質1,2)。

例:poj1631

/**

最長遞增子串行o(nlogn)演算法:

狀態轉移方程:f[i] = max,1<=j=f[y],則x相對於y更有潛力。

首先根據f值分類,記錄滿足f[t]=k的最小的值a[t],記d[k]=min,f[t]=k.

1.發現d[k]在計算過程中單調不上公升

2.d[1]#include #include using namespace std;

const int n = 41000;

int a[n]; //a[i] 原始資料

int d[n]; //d[i] 長度為i的遞增子串行的最小值

int binsearch(int key, int* d, int low, int high)

return 0;

}int lis(int* a, int n, int* d)

return len;

}int main()

return 0;

}

最長上公升子串行 O nlogn

題目描述 input 輸入乙個整數n 表示接下來有 n 個數輸入。output 輸出當前數列最長上公升子串行的長度。直接上 最長下降子串行 最長山峰序列都可以以該問題為母問題 進行延伸。include include using namespace std define max 1000 int s...

最長上公升子串行O nlogn

假設已經計算出的兩個狀態a和b滿足a a a b 且d a d b 則對於後續所有的狀態i 即i a且i b 來說,a並不會比b差 如果b滿足a b a i 的條件,a肯定也滿足,且二者的d值相同 但反過來卻不一定了,a滿足a a a i 的條件時,b卻不一定滿足。換句話說,如果我們只保留a,一定不...

最長上公升子串行O nlogn

令a i 表示輸入第i個元素,d i 表示從a 1 到a i 中以a i 結尾的最長子序列長度。對於任意的0 j i 1,如果a j a i 則a i 可以接在a j 後面形成乙個以a i 結尾的新的最長上公升子串行。對於所有的 0 j i 1,我們需要找出其中的最大值。dp狀態轉移方程 d i m...