洛谷 P1020 導彈攔截

題目描述

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

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

輸入輸出格式

輸入格式:

 

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

 

輸出格式:

 

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

 

輸入輸出樣例

輸入樣例#1: 

389 207 155 300 299 170 158 65

輸出樣例#1: 

6
2

解法:優化的最長上升子序列問題

最近經常遇到這一類的dp。今天選拔賽也遇到一道用n^2算法但始終超時。

一直沒有 學會這個NlogN算法的姿勢。

現在學習一波。

 

#include <iostream>
#include <algorithm>
#include <climits>
#include <cstring>
#include <vector>
#include <map>
#define pii pair<int, int>
#define vi vector<int>
#define ll long long
#define eps 1e-5
using namespace std;
const int maxn = 2e5 + 10;
int a[maxn];
int dp[maxn];
int asc[maxn];
map<int, int> vis;
int main()
{
    // freopen("/Users/vector/Desktop/testdata.in", "r", stdin);
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n = 0;
    while(cin >> a[n++]);
    int len = 0;

    memset(dp, 0, sizeof(dp));
    for(int i = 0; i < n; i++)
    {
        *upper_bound(dp, dp + n, a[i], greater<int>()) = a[i];
    }
    len = lower_bound(dp, dp + n, 0,greater<int>()) - dp;
    cout << len << endl;
    memset(asc, 1, sizeof(asc));
    for(int i = 0; i < n; i++)
    {
        *lower_bound(asc, asc + n, a[i]) = a[i];
    }
    len = lower_bound(asc, asc + n, 0x1010101) - asc;
    cout << len << endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章