某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。
輸入飛彈依次飛來的高度(雷達給出的高度資料是≤50000的正整數),計算這套系統最多能攔截多少飛彈,如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。
輸入格式:
111行,若干個整數(個數≤10000)
輸出格式:
2行,每行乙個整數,第乙個數字表示這套系統最多能攔截多少飛彈,第二個數字表示如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。
題意已經明顯告訴你讓你求乙個最長不上公升子串行和乙個最長上公升子串行
o(n^2)的演算法大家應該都會,現在的問題是如何優化
我們以第一問為例
首先記下在當前位置之前長度為k的最長不下降子串行的結尾最大是什麼(如果沒有,就記為0)
然後,我們得出乙個單調性:長度越長,必然高度越低
(因為乙個較長的必定由乙個較短的轉移而來,由最長不上公升子串行的性質可得,後者高度小於等於前者高度)
我們就可以用二分查詢的方式找到轉移點轉移
不過記住,轉移後要更新長度為當前位置長度的最長不下降子串行的結尾
#include#include#include
#define rii register int i
#define rij register int j
using
namespace
std;
int dp[100005],n,m,cd[100005],h[100005
],ans;
intmain()
cd[0]=2147483647
; n=1
;
while(~scanf("
%d",&h[n]))
n--;
for(rii=1;i<=n;i++)
else
break
; }
int mid=(l+r)/2
;
if(cd[mid]else
}ans=max(ans,dp[i]);
}cout
for(rii=0;i<=100005;i++)
ans=0
; memset(dp,
0,sizeof
(dp));
cd[0]=0
;
for(rii=1;i<=n;i++)
else
break
; }
int mid=(l+r)/2
;
if(cd[mid]>=h[i])
else
}ans=max(ans,dp[i]);
}cout
<}
攔截飛彈,最長非上公升子串行,DP 二分
題目描述 某國為了防禦敵國的飛彈襲擊,開發出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲,並觀測到飛彈依次飛來的高度,請計算這套系統最多能攔截多少飛彈。攔截來襲飛彈時,必須按來襲飛彈襲...
飛彈攔截 二分 dilworth定理)
原題 接下來是dilworth定理 關鍵就是 如果是求下降子串行的最小劃分,相當於是求最小反鏈劃分,等於最長不下降子串行的長度。求 下降子串行的最小劃分 等於最長非下降子串行長度 確定 求非上公升子串行的最小劃分 等於最長非下降子串行長度還是等於最長上公升子串行長度?1 const int inf ...
DP最長子序列 (常規加二分)
所有的最長子序列都差不多,只是 的區別,所以要注意符號問題,之前學過常規寫法,今天又看到了乙個二分寫法,時間複雜度前者為n n,後者為nlogn,所以學一學還是很有必要的,挑了一道自己oj上的dp水題 傳送門 最長不上公升子串行 常規寫法很簡單,也當是複習了 include include incl...