1025 用到了LIS)(DP 二分優化)

2021-08-11 16:23:41 字數 2458 閱讀 2828

題目的意思是,兩行城市,從左到右為1,2,3……n個城市。上面的下面的城市要與上面某個的城市相連,在不出現相交的情況下,最多可以連多少條

最長上公升子串行的o(n*logn)演算法分析如下:

先回顧經典的o(n^2)的動態規劃演算法,設a[t]表示序列中的第t個數,dp[t]表示從1到t這一段中以t結尾的最長上公升子串行的長度,初始時設dp [t] = 0(t = 1, 2, ..., len(a))。則有動態規劃方程:dp[t] = max (j= 1, 2, ..., t - 1, 且a[j]

現在,我們仔細考慮計算dp[t]時的情況。假設有兩個元素a[x]和a[y],滿足 

(1)x 

(2)a[x] 

(3)dp[x] = dp[y]

此時,選擇dp[x]和選擇dp[y]都可以得到同樣的dp[t]值,那麼,在最長上公升子串行的這個位置中,應該選擇a[x]還是應該選擇a[y]呢? 

很明顯,選擇a[x]比選擇a[y]要好。因為由於條件(2),在a[x+1] ... a[t-1]這一段中,如果存在a[z],a[x] 

再根據條件(3),我們會得到乙個啟示:根據dp的值進行分類。對於dp的每乙個取值k,我們只需要保留滿足dp[t] = k的所有a[t]中的最小值。設d[k]記錄這個值,即d[k] = min (dp[t] = k)。 

注意到d的兩個特點: 

(1) d[k]的值是在整個計算過程中是單調不上公升的。 

(2) d的值是有序的,即d[1] 

利用d,我們可以得到另外一種計算最長上公升子串行長度的方法。設當前已經求出的最長上公升子串行長度為len。先判斷a[t]與d[len]。若a [t] > d[len],則將a[t]接在d[len]後將得到乙個更長的上公升子串行,len = len + 1, d[len] = a [t];否則,在d[1]..d[len]中,找到最大的j,滿足d[j]

在上述演算法中,若使用樸素的順序查詢在d[1]..d[len]查詢,由於共有o(n)個元素需要計算,每次計算時的複雜度是o(n),則整個演算法的時間複雜度為o(n^2),與原來的演算法相比沒有任何進步。但是由於d的特點(2),我們在d中查詢時,可以使用二分查詢高效地完成,則整個演算法的時間複雜度下降為o(nlogn),有了非常顯著的提高。需要注意的是,d在演算法結束後記錄的並不是乙個符合題意的最長上公升子串行!

例如2 5 4 6 3 8 7

2 3 6 7

nlogn的dp的思路大概就是給你乙個數,插到乙個陣列中,該位置已存在,就覆蓋它。也就是可以用二分查詢提高效率。

另為一種o(nlogn)演算法,這種演算法的操作如下:

開乙個棧,每次取棧頂元素top和讀到的元素temp做比較,如果temp > top 則將temp入棧;如果temp < top則二分查詢棧中的比temp大的第1個數,並用temp替換它。最長序列長度即為棧的大小top。

這也是很好理解的,對於x和y,如果x < y且stack[y] < stack[x],用stack[x]替換stack[y],此時的最長序列長度沒有改變但序列q的''潛力''增大了。

舉例:原序列為1,5,8,3,6,7

棧為1,5,8,此時讀到3,用3替換5,得到1,3,8;再讀6,用6替換8,得到1,3,6;再讀7,得到最終棧為1,3,6,7。最長遞增子串行為長度4。

這道題顯然是用第二種演算法(1 <= n <= 50w),**如下:

#include 

<

stdio.h

>

#define

n 500005

intnum[n], dp[n]; //這邊初始化dp 自己認為dp裡面是1 2 3 4 5 6 7 8 9 .....50005

intfind(

intlow,

inthigh,

inti)

//二分法查詢 確定num[i]的位置

return

low;

//返回其位置 返回不大於num【i】的 最小座標

}int

main()

dp[1] =

num[

1];

len =1

;for

(i =

2; i

<=

n; i

++) //從第二個貧窮城市的選擇開始

if(len ==1

) printf(

"case %d:\nmy king, at most %d road can be built.\n\n",

++case, len);

else

printf(

"case %d:\nmy king, at most %d roads can be built.\n\n",

++case, len);

}return0;

}

終於用到了fflush

今天遇到一 怪事 程式正常輸出幾千條log資訊,能全部輸出,但是通過重定向到乙個檔案中時總是少那麼幾十條,嘗試了輸出 2000,3000條結果差不多。後來小吳告訴我說是行緩衝的問題,果然如此,加上個fflush 就行了。為什麼會遇到這個問題?1.我們希望實現isakmp的橢圓曲線金鑰交換,因此需要先...

終於用到了DevCpp

幾天前就收到到了小菜給我發短訊息,不好意思,今天才拿出來看。不是我人品問題 輕易得相信狒狒 的確,在關於it方面,我們在校的學生得和狒狒們多交流,畢竟他們在工作了。來自xiaocai0001 c primer 我還沒有完整的看過,只是掃過幾眼.現在的編譯器不外有幾種,一種gcc系列的,像linux自...

我終於用到了泛型

我終於用到了泛型 左直拳 泛型是。net2。0出現的新東西。慚愧,3。0已經出了很久了,可我現在才開始用。落後啊落後,簡直屎一堆。delegate void setenablecallback system.windows.forms.control objctrl,bool enable 宣告 p...