There are nn beautiful skyscrapers in New York, the height of the ii-th one is hihi. Today some villains have set on fire first n−1n−1 of them, and now the only safety building is nn-th skyscraper.
Let's call a jump from ii-th skyscraper to jj-th (i<ji<j) discrete, if all skyscrapers between are strictly lower or higher than both of them. Formally, jump is discrete, if i<ji<j and one of the following conditions satisfied:
- i+1=ji+1=j
- max(hi+1,…,hj−1)<min(hi,hj)max(hi+1,…,hj−1)<min(hi,hj)
- max(hi,hj)<min(hi+1,…,hj−1)max(hi,hj)<min(hi+1,…,hj−1).
At the moment, Vasya is staying on the first skyscraper and wants to live a little longer, so his goal is to reach nn-th skyscraper with minimal count of discrete jumps. Help him with calcualting this number.
Input
The first line contains a single integer nn (2≤n≤3⋅1052≤n≤3⋅105) — total amount of skyscrapers.
The second line contains nn integers h1,h2,…,hnh1,h2,…,hn (1≤hi≤1091≤hi≤109) — heights of skyscrapers.
Output
Print single number kk — minimal amount of discrete jumps. We can show that an answer always exists.
Examples
Input
5 1 3 1 4 5
Output
3
Input
4 4 2 2 4
Output
1
Input
2 1 1
Output
1
Input
5 100 1 100 1 100
Output
2
Note
In the first testcase, Vasya can jump in the following way: 1→2→4→51→2→4→5.
In the second and third testcases, we can reach last skyscraper in one jump.
Sequence of jumps in the fourth testcase: 1→3→51→3→5.
题意:
一个人需要从第 1 栋楼跳到第 n 栋楼,每栋楼有个高度 h[i],每次只能进行以下三种跳跃之一:
(1)从 i - 1 跳到 i
(2)从 j 跳到 i ,且 j 和 i 之间楼的高度 < min(h[j], h[i])
(3)从 j 跳到 i ,且 j 和 i 之间楼的高度 > max(h[j], h[i])
问最少跳多少次
思路:
单调栈维护第 i 栋楼可以从之前的哪些楼跳过来。单增栈维护第(3)种跳跃方式,单减栈维护第(2)种跳跃方式,再加上每一栋楼都可以从前一栋楼跳过来。于是对于任意一对 j、 i,j 可以跳到 i,有转移方程dp[i] = min(dp[i], dp[j] + 1)
(以单增栈为例)一个未进栈的高度可以由当前栈顶比它大的高度转移过来,然后pop掉这些比它大的高度,如果遇到相同的高度,只能由栈顶的这个相同高度转移过来,虽然当前栈顶和栈顶的下一个高度相同,但是可能在原序列中它们并不是相邻的,比如原序列 2 3 4 5 2 2,当前栈:2 2,下一个进栈高度:2,栈中这两个2之间原本存在3 4 5,即原序列最后一个2不可以从第一个2转移过来。所以相同高度只能转移一个,并且还要在转移之后把相同高度全部pop掉。
#include<bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 3e5+7;
int a[maxn];
int dp[maxn];
int main()
{
int n;
cin >> n;
for(int i = 1; i<= n; i++){
scanf("%d", &a[i]);
}
memset(dp, inf, sizeof(dp));
stack<int> st1, st2;
dp[1] = 0;
st1.push(1), st2.push(1);
for(int i = 2; i <= n; i++) {
dp[i] = min(dp[i], dp[i - 1] + 1);
///单增栈
while(!st1.empty() && a[st1.top()] > a[i]) {
dp[i] = min(dp[i], dp[st1.top()] + 1);
st1.pop();
}
if(!st1.empty())
dp[i] = min(dp[i], dp[st1.top()] + 1);
while(!st1.empty() && a[st1.top()] == a[i]) st1.pop();
st1.push(i);
///单减栈
while(!st2.empty() && a[st2.top()] < a[i]) {
dp[i] = min(dp[i], dp[st2.top()] + 1);
st2.pop();
}
if(!st2.empty())
dp[i] = min(dp[i], dp[st2.top()] + 1);
while(!st2.empty() && a[st2.top()] == a[i]) st2.pop();
st2.push(i);
}
cout << dp[n] << endl;
}