题目1500:出操队形

#include <stdio.h>
 
#define MAX 1000001
 
int student[MAX];
int cnt[MAX];//cnt[i]表示以i为“峰顶”的最长子序列
int dp[MAX];
 
int BSearch(int dp[], int start, int end, int key){//搜索大于等于key的第一个元素的位置
    int middle;
    while (start <= end){
        middle = ((end - start) >> 1) + start;
        if (dp[middle] < key)
            start = middle + 1;
        else if (dp[middle] > key)
            end = middle - 1;
        else
            return middle;
    }
    return start;
}
 
int Insert(int data, int *nMax){//找到以data为结尾的上升子序列的长度,并返回
    int j = BSearch(dp, 0, *nMax, data);
    if (j > *nMax){
        *nMax = j;
        dp[j] = data;
    }
    else if (dp[j-1] < data && data < dp[j]){
        dp[j] = data;
    }
    return j;
}
 
void LIS(int n){//求以student[i]为结尾的上升子序列的长度
    int i;
    int nMaxLIS = 1;
    dp[0] = -1;
    dp[1] = student[1];
    cnt[1] = 1;
    for (i = 2; i <= n; ++i){
        cnt[i] = Insert(student[i], &nMaxLIS);
    }
}
 
void LDS(int n){//求以student[i]为开头的下降子序列的长度
    int i;
    int nMaxLDS = 1;
    dp[0] = -1;
    dp[1] = student[n];
    for (i = n - 1; i >= 1; --i){
        cnt[i] += Insert(student[i], &nMaxLDS) - 1;
    }
}
 
int main(void){
    int n, i;
    int max;
    while (scanf("%d", &n) != EOF){
        for (i = 1; i <= n; ++i)
            scanf("%d", &student[i]);
        LIS(n);
        LDS(n);
        max = -1;
        for (i = 1; i <= n; ++i)
            if (max < cnt[i])
                max = cnt[i];
        printf("%d\n", n - max);
    }
 
    return 0;
}
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值