选择子序列 51Nod - 1153

长度为N的整数数组A,所有的数均不相同,假设下标从0开始。找到一个最长的数组B,B数组的长度为K,数值范围是0 - N - 1,记录的是A数组的下标。满足A B[0 ] > A B[1 ] > A B[2 ] >...A B[K ],并且对任意连续的两项B i 及B i+1 ,满足min(B i ,B i+1 ) < j < max(B i ,B i+1 ) 均有A j < A B[i+1
] ,求最大的K。例如:9, 10, 2, -1, 3, -5, 0, -3, 1, 12, 5, 8, -2, 6, 4。可以选出:12, 10, 3, 1, 0, -3。对应的下标为:9, 1, 4, 8, 6, 7(就是B数组),输出6。
Input
第1行:一个数N,表示A数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数对应A数组的元素Ai(0 < Ai < 10^9)
Output
输出B数组最长的长度K。
Sample Input
15
9
10
2
-1
3
-5
0
-3
1
12
5
8
-2
6
4
Sample Output
6
一道单调栈的题,具有这种“阻止”的特征,就是说不能越界的特点,我们的栈中正好保留着那些可能的隔离点。
#include <stdio.h>
#include<stack>
using namespace std;
const int maxn=50010;

stack<int> stk;
struct node{
    int val;
    int max_len;
}s[maxn];

int max_val(int a,int b){
    if(a>b)
        return a;
    return b;
}
/*
一个单调栈的问题,现在想想可能有点感觉了,要求 l~r,中间的值都小于两边的值,
这就很像单调栈的问题,就是保留一个连续的递减的序列,中间进行一些操作
只保留那些高的点
*/

int main()
{
    int n;
    scanf("%d",&n);
    int ans=0;
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i].val);
        int temp_len=0;
        while(!stk.empty()){
            int now=stk.top();
            if(s[i].val>s[now].val){
                temp_len=max(temp_len,s[now].max_len);
                stk.pop();
            }
            else{
                break;
            }
        }
        temp_len++;
        temp_len=max_val(temp_len,stk.size()+1);//注意这里,一个是我们进行中间的”精简“,还有就是保留的递减序列
        s[i].max_len=temp_len;
        ans=max(ans,s[i].max_len);
        stk.push(i);
    }
    printf("%d\n",ans);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值