P1020 飛彈攔截

2022-05-18 06:23:17 字數 3338 閱讀 8371

提交 115.78k

通過 24.09k

時間限制 1.00s

記憶體限制 125.00mb

題目提供者ccf_noi

難度普及/提高-

歷史分數200

提交記錄

檢視題解

noip普及組

special judge

1999

檢視演算法標籤

進入討論版

檢視討論

檢視推薦

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

輸入飛彈依次飛來的高度(雷達給出的高度資料是≤50000 \le 50000≤50000的正整數),計算這套系統最多能攔截多少飛彈,如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。

111行,若干個整數(個數≤100000 \le 100000≤100000)

222行,每行乙個整數,第乙個數字表示這套系統最多能攔截多少飛彈,第二個數字表示如果要攔截所有飛彈最少要配備多少套這種飛彈攔截系統。

輸入 #1

389 207 155 300 299 170 158 65

輸出 #1

6

2

為了讓大家更好地測試n方演算法,本題開啟spj,n方100分,nlogn200分

每點兩問,按問給分

對於第一問,顯然是讓我們求乙個最長不上公升子串行。

如何o(nlogn)來求lcs:建立乙個陣列來模擬單調棧,儲存乙個不上公升序列,依次將飛彈高度插進去,如果當前飛彈等於或者低於棧頂的飛彈高度,顯然可以直接加進去;不然,如果當前飛彈高於棧頂的飛彈高度,就可以使用c++內建函式upperbound來在陣列中尋找乙個能把當前飛彈塞進去的位置。

int p = upper_bound(d + 1, d + 1 + len, a[i], greater () ) - d;

d[p] = a[i];

如此一來,陣列的size就是我們的答案了。

對於第二問,是要把整個陣列劃分為n個不重複的不上公升子串行,可以轉化為求乙個lis,證明如下:

(1)假設打飛彈的方法是這樣的:取任意乙個飛彈,從這個飛彈開始將能打的飛彈全部打完。而這些飛彈全部記為為同一組,再在沒打下來的飛彈中任選乙個重複上述步驟,直到打完所有飛彈。

(2)假設我們得到了最小劃分的k組飛彈,從第a(1<=a<=k)組飛彈中任取乙個飛彈,必定可以從a+1組中找到乙個飛彈的高度比這個飛彈高(因為假如找不到,那麼它就是比a+1組中任意乙個導更高,在打第a組時應該會把a+1組所有飛彈一起打下而不是另歸為第a+1組),同樣從a+1組到a+2組也是如此。那麼就可以從前往後在每一組飛彈中找乙個更高的連起來,連成一條上公升子串行,其長度即為k;

(3)設最長上公升子串行長度為p,則有k<=p;又因為最長上公升子串行中任意兩個不在同一組內(否則不滿足單調不公升),則有p>=k,所以k=p。

1 #include 2

#define dbg(x) cout << #x << "=" << x << endl34

using

namespace

std;

5 typedef long

long

ll;6

const

int maxn = 1e5 + 7;7

8int f1[maxn];///

lcs9

int f2[maxn];///

lis10

inta[maxn];

11int

len1, len2;

1213

namespace

_buff

21return ib == ie ? -1 : *ib++;22}

23}2425

intread()

33if (c == '-'

) 37

for (; c >= '

0' && c <= '

9'; c =getc())

40return pos ? ret : -ret;41}

4243

intmain()

4457

else

62if(f2[len2] 65else69}

70 printf("

%d\n%d\n

",len1, len2);

71return0;

72 }

1 #include 2

#define dbg(x) cout << #x << "=" << x << endl34

using

namespace

std;

5 typedef long

long

ll;6

7 templateinline void read(t &res)813

14namespace

_buff

22return ib == ie ? -1 : *ib++;23}

24}2526

intqread()

34if (c == '-'

) 38

for (; c >= '

0' && c <= '

9'; c =getc())

41return pos ? ret : -ret;42}

4344

const

int kmaxn = 1007;45

ll f[kmaxn][kmaxn];

46const ll mod = 1e9 + 7;47

intn;

48ll p[kmaxn];

4950

intmain()

5156 f[0][0] = 1;57

for(int i = 1; i <= n; ++i) 62}

63for(int i = 0; i < n; ++i)

66 printf("

%lld\n

",f[n][n]);

67return

0;

P1020 飛彈攔截

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

P1020 飛彈攔截

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

P1020 飛彈攔截

原題鏈結 貪心 記錄每套系統攔截過的最小高度 新來的飛彈 如果高於所有飛彈的最低高度 那就只能再加一套了嘛 如果低於某些系統的最低高度 那就貪心 把它加到 最低高度最低的一套系統內 include include include include include include include inc...