洛谷P1020 最长不上子序列及其个数

版权声明:转载请注明出处 https://blog.csdn.net/jay__bryant/article/details/81590812

题目大意:输入若干导弹的高度,用炮弹拦截,第一发炮弹能达到任意高度,第i发炮弹不能高于第i-1发炮弹。求一个炮弹系统能拦截的最多的导弹和若要拦截所有的导弹最少需要有多少炮弹系统

第一问即求最长不上升子序列的长度
第二问即求最长不上升子序列的个数
而求最长不上升子序列的个数即求最长上升子序列的长度
简单证明:因为在序列中的每一次数据的上升意味着最长不上升子序列有一个新的起点

#include <cstdio>
#include <sstream>
#include <iostream>

using namespace std;
const int maxn = 1e5 + 10;
const int INF = 2147483640;
int dp[maxn];
int a[maxn];

int bin_find1(int l, int r, int key)
{
    int mid;
    while(l <= r)
    {
        mid = (l+r)>>1;
        if(key > dp[mid]) r = mid - 1;
        else l = mid + 1;
    }
    return r + 1;
}

int bin_find2(int l, int r, int key)
{
    int mid;
    while(l <= r)
    {
        mid = (l+r)>>1;
        if(key <= dp[mid]) r = mid - 1;
        else l = mid + 1;
    }
    return r + 1;
}


int main()
{
    int i;
    int n = 0;//a[]长度
    int len = 0;
    int pos;
    while(~scanf("%d", &a[++n])) ;
    --n;
    dp[0] = INF;
    for(i = 1; i <= n; ++i)
    {
        if(a[i] <= dp[len]) dp[++len] = a[i];
        else
        {
            pos = bin_find1(1, len, a[i]);
            dp[pos] = a[i];
        }
    }
    printf("%d\n", len);
    //第二问
    len = 0;
    dp[0] = -INF;
    for(i = 1; i <= n; ++i)
    {
        if(a[i] > dp[len]) dp[++len] = a[i];
        else
        {
            pos = bin_find2(1, len, a[i]);
            dp[pos] = a[i];
        }
    }
    printf("%d\n", len);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jay__bryant/article/details/81590812