1. 程式人生 > 實用技巧 >Codeforces Round #669 (Div. 2) D

Codeforces Round #669 (Div. 2) D

題目

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\n",dp[n-1]);
   return 0;	
}