某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷:雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。
輸入飛彈依次飛來的高度(雷達給出的高度資料是≤50000的正整數),計算這套系統最多能攔截多少飛彈,如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。
輸入格式:
1行,若干個整數(個數≤100000)
輸出格式:
2行,每行乙個整數,第乙個數字表示這套系統最多能攔截多少飛彈,第二個數字表示如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。
輸入輸出樣例
輸入樣例#1:
389 207 155 300 299 170 158 65輸出樣例#1:
62————————————————————————分割線——————————————————————————
第一問:
第一問其實看似沒有思路,最多能攔截多少飛彈,但其實,再看一下題目,發現這個攔截系統能攔截的飛彈高度其實是呈不上公升序列的那麼最多能夠攔截的很明顯就是最長不上公升子串行,拿這一問就簡單了
不過,平常學的dp做法都是n^2做法,看看資料100000,很明顯超時了
所以我這裡介紹一種nlogn的做法(其他同理,包括最長不下降子串行等):
定義乙個f陣列,其中f[i]表示長度為i不上公升子串行的最後一位數
len表示最長不上公升子串行長度 初始化len=0;f[0]=1e9 (正的無限大)
那麼,如果high[i](1<=i<=number;表示飛彈高度)<=f[len] f[++len]=high[i]
什麼意思呢?若當前飛彈高度小於等於長度為len的不上公升子串行的最後乙個數,那麼代表這個數是可以加入這個子串行的,此時f[len]要更新成為這個數
否則的話,在f[0——len]中間二分,尋找第乙個大於等於high[i]的數f[j],找到以後,再把high[i]加入到此時f[j]末尾
**如下(有點亂,有壓行的行為):
if(high[i]<=f[len1])f[++len1]=high[i];第二問:剛看到第二問,就想到了貪心,不過很明顯超時了(畢竟是n方)else
f[l]=max(f[l],high[i]);
}
那我們可以推一下
假設乙個序列為:7 2 3 9 7 2 3 8 n=8
很明顯,手推出來需要4個
用柱形圖表示如下:
那麼序號為:1,3,6為乙個,4,5,7為乙個,2,8各乙個,合起來為四個
若將一組中柱形圖頂部連線起來大概若為下圖:
那麼可以發現每條直線的左端點(若為點則為這個點)呈上公升趨勢證明:用反證法
共ans條直線(ans為答案),dd[i]為第i條直線左端點數值
假設dd[i-1]>=dd[i],
那麼dd[i-1]這個的應該存在於第i條直線上(直線呈不上公升趨勢),可以用乙個攔截系統攔截
所以與題意相矛盾,故證得dd[i-1]
#includeusing如果本蒟蒻有沒有講清楚的地方,可以自己畫圖模擬,或許可以幫助你namespace
std;
int number,high[100003],f[100003],dp[100003
],len1,len2;
intmain()
f[l]=max(f[l],high[i]);
}if(high[i]>dp[len2])dp[++len2]=high[i];
else
dp[l]=min(dp[l],high[i]);}}
cout
return0;
}
(洛谷ac200題紀念)orz
洛谷P1020 飛彈攔截
某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。輸入飛彈依次飛來的高度 雷達給出...
洛谷 P1020 飛彈攔截
題目大意 對於乙個飛彈攔截系統 它的第一發炮彈能夠攔截任意高度的飛彈,但之後攔截的每一發炮彈都不能高於前一發的高度。輸入n發飛彈依次飛來的高度a i 計算這套系統最多能攔截多少飛彈,如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。1 n 100 0 a i 30000 題解 p i 表示攔截了第...
洛谷 P1020 飛彈攔截
某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。輸入飛彈依次飛來的高度 雷達給出...