luogu P1020 飛彈攔截

2021-10-04 09:01:26 字數 1574 閱讀 5551

p1020 飛彈攔截

題目詳情

題目分析:一開始用的單調棧,後來發現不行,因為如果我們假設有這樣的序列:

3 2 1 99 1
當遍歷到99時,我們的棧會被我們自動清除,這時最後的最長不上公升序列就只有3,而正確答案是4

upper_bound()返回有序序列中第乙個大於查詢值的指標。

lower_bound()返回有序序列中第乙個大於等於查詢值的指標。

思路這道題只有o(nlogn)的演算法才能得200分;

我們有乙個棧,遍歷飛彈高度,如果飛彈高度小於等於棧頂元素,就壓入棧頂,如果大於,就在棧中二分查詢第乙個比這個高度小的元素並替換它。

為什麼這樣替換是正確的?

我們知道飛彈只能按時間順序打下來,不可能先打後面來的飛彈,再打前面的飛彈,那替換操作難道不會導致這樣的情況嗎?

我們知道只要這個元素不是棧頂元素,那這個元素永遠都不會用到,因為我們的比較只跟棧頂元素有關,當我們替換乙個元素的時候是不影響結果的,如果這時的飛彈高度塞進去了,棧依然會保持有序。如果恰好這個飛彈以後最長不上公升序列比替換後的現有的序列要長,那後面的遍歷中會乙個乙個的把現在的就序列換掉,最後變成乙個更長的序列。而如果以後的最長不上公升序列沒有現在長,雖然中間有元素被替換了,但不影響原來的長度。

#include

#include

#include

//greater的標頭檔案

using

namespace std;

int a[

111111

], num, sta1[

111111

], top, sta2[

111111

], topp;

intmain()

printf

("%d\n%d\n"

, top +

1, topp +1)

;//棧是從0開始標的,所以加一。

}

這是o(n

2n^2

n2)的演算法。

#include

#include

using

namespace std;

int a[

111111

], ans, num, an, sta1[

111111

], top, sta2[

111111

], topp;

intmain()

printf

("%d\n",*

max_element

(sta1 +

1, sta1 + num));

for(

int i =

1; i <= num -

1; i++

)printf

("%d\n",*

max_element

(sta2 +

1, sta2 + num));

}

Luogu p1020飛彈攔截

dp的做法,複雜度是 o n 2 只能得100分,乙個dp求的是最長下降子串行長度,乙個dp求的是最少有多少個最長不上公升序列,includeusing namespace std const int maxn 1e5 5 int f maxn int dp maxn int main n dp 1...

1020 飛彈攔截

難度 普及 提高 題目型別 動規 提交次數 1 涉及知識 線性動規 某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套...

P1020 飛彈攔截

題目描述 某國為了防禦敵國的飛彈襲擊,發展出一種飛彈攔截系統。但是這種飛彈攔截系統有乙個缺陷 雖然它的第一發炮彈能夠到達任意的高度,但是以後每一發炮彈都不能高於前一發的高度。某天,雷達捕捉到敵國的飛彈來襲。由於該系統還在試用階段,所以只有一套系統,因此有可能不能攔截所有的飛彈。輸入飛彈依次飛來的高度...