hdu 1025 dp 二分 模板

2021-07-09 22:23:35 字數 1497 閱讀 3865

題意:

在一條河的兩邊各有n個位置,在這些位置之間建橋,要求所有橋之間不能交叉。現在告訴你所有可以建橋的位置,例如2,4,就是說河左邊的位置2可以與河右邊的位置4之間建橋,現在要求滿足要求的情況下最多可以建橋的個數。

分析:想了好久發現是乙個最長上公升子串行問題,當時n比較大,所以一般的dp演算法不能解決這個問題,所以我們換一種專門解決這個問題的特殊解法,就是用dp+二分,但是只能解決序列的長度而不能求出序列。

下面的解釋摘自lce_crazy的部落格。

假定存在乙個序列d[1...9]=2 1 5 3 6 4 8 9 7,可以看出lis長度為5。現在開始一步一步的找出來最終的結果。

定義序列b,令i=1...9來逐個考察。此外用變數len來記錄現在最長算到了多少了。

首先,把d[1]放到b裡,即b[1]=d[1],就是說長度為1的lis的最小末尾是2,這時len=1,然後把d[2]有序的放到b裡,令b[1]=1(d[2]),就是說長度為1的lis最小末尾是1,d[1]=2已經沒有用了,這是len=1不變。接著d[3]=5,5>1,所以令b[1+1]=d[3]=5,就是說長度為2的lis的最小末尾是5,此時b[1...2]=1,5,len=2。

再來,d[4]=3,它正好在1和5之間,當然放在1的位置上不合適,因為1<3,因此長度為2的最小末尾應該是3,淘汰掉5,這時候b[1...2]=1,3,len=2,繼續d[5]=6,它在3後邊,所以b[3]=4,b[1...3]=1,3,6,len=3。

第6個,d[6]=4,它加在3和6之間,所以我們把6換掉,這樣b[1...3]=1,3,4,len=3。

第7個,d[7]=8,8>4,所以b[4]=8,b[1...4]=1,3,4,8,len=4。

第8個,d[8]=9,b[1...5]=1,3,4,8,9,len=5。

最後乙個,d[9]=7,所以b[1...5]=1,3,4,7,9,len=5。

注意這裡的b並不是lis,而是對應長度的lis的最小末尾。

現在可以發現b插入資料是有序的,而且進行替換而不需要移動,也就是說可以使用二分查詢,時間複雜度就降下來了。

//之前見過的建橋問題建橋問題

//求最長上公升子串行的長度,n比較大,不能用普通的dp,會超時

//只求長度,可以用dp+二分

#include #include #include #include using namespace std;

int num[50001];

int ans[50001];

int main()

printf("case %d:\n",k);

if(len==1)

printf("my king, at most 1 road can be built.");

else

printf("my king, at most %d roads can be built.",len);

printf("\n\n");

k++;

}return 0;

}

hdu 2604 DP 矩陣二分

實際上就是這樣乙個問題,乙個序列僅由1和0組成,問n位不帶101和111子串行有多少個,結果模m 話說這是集訓的一道題,當時完全沒思路,今天做了一下,還是沒有做出來,不過好歹還會用最裸的記憶化搜尋。但肯定超時 話說集訓那時真的弱爆了。超弱的1b 看了下解題報告,發現1維dp既能搞定,再用矩陣二分。其...

hdu 3586 樹形dp 二分

題意 給n個節點的樹,要求使葉子節點與根斷開,割掉的邊的權值和不超過m。求這些被割邊的權值最大中的最小。dp u min dp v w w 為 u 到 v 的權值。如果w 大於二分的 mid dp u dp v 二分列舉邊權。include include include includeusing ...

hdu 3586 樹形dp 二分

題目大意 給定n個敵方據點,1為司令部,其他點各有一條邊相連構成一棵 樹,每條邊都有乙個權值cost表示破壞這條邊的費用,葉子節點為前線。現要切斷前線和司令部的聯絡,每次切斷邊的費用不能超過上限limit,問切斷所 有前線與司令部聯絡所花費的總費用少於m時的最小limit。1 n 1000,1 m ...