长度为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
Input
第1行:一个数N,表示A数组的长度。(1 <= N <= 50000)
第2 - N + 1行:每行1个数对应A数组的元素Ai(0 < Ai < 10^9)
Output
输出B数组最长的长度K。
Sample Input
Sample Output
一道单调栈的题,具有这种“阻止”的特征,就是说不能越界的特点,我们的栈中正好保留着那些可能的隔离点。
] ,求最大的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。
第2 - N + 1行:每行1个数对应A数组的元素Ai(0 < Ai < 10^9)
15 9 10 2 -1 3 -5 0 -3 1 12 5 8 -2 6 4
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);
}