题目
There are n beautiful skyscrapers in New York, the height of the i-th one is hi. Today some villains have set on fire first n−1 of them, and now the only safety building is n-th skyscraper.
Let's call a jump from i-th skyscraper to j-th (i<j) discrete, if all skyscrapers between are strictly lower or higher than both of them. Formally, jump is discrete, if i<j and one of the following conditions satisfied:
i+1=j
max(hi+1,…,hj−1)<min(hi,hj)
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 n-th skyscraper with minimal count of discrete jumps. Help him with calcualting this number.
Input
The first line contains a single integer n (2≤n≤3⋅105) — total amount of skyscrapers.
The second line contains n integers h1,h2,…,hn (1≤hi≤109) — heights of skyscrapers.
Output
Print single number k — minimal amount of discrete jumps. We can show that an answer always exists.
分析
我们可以选择相邻之间跳,或者是之间都小于或者大于的跳,那么看样子是dp,相邻之间跳很简单,然后第二个要求的话我们可以用单调队列优化一下,维护一个长度上升和长度下降的坐标序列,一旦不符合单调性,那么说明我们需要在单调队列里面去掉的这些元素我们都是可以跳走的,然后进行dp转移就好了。
代码实现
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;};
void check_max (int &a,int b) { a=max (a,b);}
void check_min (int &a,int b) { a=min (a,b);}
inline int read() {
char ch=getchar(); int x=0, f=1;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
} while('0'<=ch&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
} return x*f;
}
const int maxn=2e3+10;
int main () {
int n;
scanf ("%d",&n);
vector <int> h(n);
rep (i,0,n-1) scanf ("%d",&h[i]);
vector <int> dp(n);
dp[0]=0;
vector <int> s{0},p{0};
rep (i,1,n-1) {
dp[i]=dp[i-1]+1;
while (!s.empty ()&&h[i]>=h[s.back ()]) {
int x=h[s.back ()];
s.pop_back ();
if (!s.empty ()&&h[i]>x) check_min (dp[i],dp[s.back ()]+1);
}
while (!p.empty ()&&h[i]<=h[p.back ()]) {
int x=h[p.back ()];
p.pop_back ();
if (!p.empty ()&&h[i]<x) check_min (dp[i],dp[p.back ()]+1);
}
s.pb (i);
p.pb (i);
}
printf ("%d
",dp[n-1]);
return 0;
}