链接:
题意:
长度为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来做。
![](https://i-blog.csdnimg.cn/blog_migrate/673ecd71be19acb756b24ef71048b032.png)
用递减栈维护最长的递减数组长度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;
}