【51Nod四级题】选择子序列

链接:
题意:
长度为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。
思路:
这道题题意有点不好理解,通俗的来说就是要找个尽可能长的数组B,然后两两之间的j,对于a[j]<a[b[i+1]]成立,这道题应该可以想到用单调递减栈+dp来做。
用递减栈维护最长的递减数组长度dp[i],同时需要出栈的时候,求出出栈元素的max{dp[j]|k<j<i},k为不能出栈的位置,然后dp[i]= max{dp[j]|k<j<i}+1,最后维护一个最大值就行了。
AC代码:
#include<bits/stdc++.h>    
#define ll long long    
#define endl "\n"    
const int MAXN=5e4+5;    
const int INF=0x3f3f3f;  
const int MOD=1e9+7;    
const double eps=1e-6;    
using namespace std;      
  
int a[MAXN],dp[MAXN],ma[MAXN];  
int main(){   
    ios::sync_with_stdio(false);  
    int n;  
    cin>>n;  
    for(int i=0;i<n;++i)  
        cin>>a[i];  
    stack<int> st;   
    for(int i=0;i<n;i++){  
        int flag=1,mav=0;   
        while(!st.empty()&&a[i]>a[st.top()]){  
            flag=0;  
            mav=max(mav,ma[st.top()]);  
            st.pop();  
        }     
        if(st.empty())  
            dp[i]=1;  
        else  
            dp[i]=dp[st.top()]+1;  
          
        if(flag)  
            ma[i]=dp[i];  
        else  
            ma[i]=mav+1;          
        st.push(i);  
    }  
    int mavv=-1;  
    for(int i=0;i<n;++i)   
        mavv=max(mavv,ma[i]);  
    cout<<mavv<<endl;  
    return 0;    
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~Lomiss~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值