1. 程式人生 > >洛谷 P1020 導彈攔截 【最長上升子序列】 || 【線段樹】

洛谷 P1020 導彈攔截 【最長上升子序列】 || 【線段樹】

PE AD 捕捉 描述 esp 數據 依次 size new

題目鏈接:https://www.luogu.org/problemnew/show/P1020

題目描述

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

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

輸入格式:

一行,若幹個整數(個數少於100000)

輸出格式:

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

輸入樣例#1:
389 207 155 300 299 170 158 65
輸出樣例#1:
6
2

下面我的代碼是WA的,只不過我還不知道為什麽WA,先記錄下來,至於線段樹做法,等以後學會了再來補吧。


#include <bits/stdc++.h>              //此題主要是不知道如何用stl中的upper_bound()函數對結構體中的某一特定元素進行二分
using namespace std;                  //當然,也可也寫一個二分子函數對該結構體進行二分,但是還是過不了,此題先記錄著吧
int arr[100010];
int vis[100010] = {0};

struct node { int val; int loc; }lis[100010]; struct cmp1 { bool operator () (const node &a, const node &b) const { return a.val < b.val; } }; int main() { int num = 0; //記錄下標記了多少個導彈 int a, len = 0,res=0; while (cin >> a) { arr[++res] = a; //
res為導彈的數量 } int ans = 0; int cas = 0; while (num != res) { for (int i = 1; i <= res; i++) { if (!vis[i]) { if (arr[i] > lis[len].val) { lis[++len].val = arr[i]; lis[len].loc = i; vis[i] = 1; } else { //*******對結構體中的某一個元素進行二分查找的方法,詳情見上面的cmp()函數 node cur; cur.val = arr[i]; int j = upper_bound(lis + 1, lis + len + 1, cur,cmp1()) - lis; //由於這是最長不上升子序列,所以用upper_bound()函數 vis[lis[j].loc] = 0; //由於原來最長上升子序列中的數此時不用了,所以要取消標記 lis[j].val = arr[i]; lis[j].loc = i; vis[i] = 1; //標記此時要用的數 } } } if (!cas)cout << len<<endl; num += len; len = 0; memset(lis, 0, sizeof(lis)); ++cas; ++ans; //導彈系統的數量 } cout << ans << endl; return 0; }



2018-05-20

洛谷 P1020 導彈攔截 【最長上升子序列】 || 【線段樹】