D. Discrete Centrifugal Jumps(單調隊列)


題:https://codeforces.com/contest/1407/problem/D

題意:給定n個數的高度,若位置 i 能跳到位置 j 得滿足以下任一條件:

  • i+1=j
  • max(hi+1,…,hj−1)<min(hi,hj)
  • max(hi,hj)<min(hi+1,…,hj−1)

   問最少多少步能從1到n

分析:

  1. 設f[i]為到達 i 的最小步數;
  2. 考慮第二操作為,假設 j 為1~i-1中大於h[i]的最靠右的位置,那么以 j 位置開始的單調遞減序列都可以一步轉移到 i ,而1~j-1位置的都不能通過操作二來一步跳到 i 位置,因為有 j 位置的“阻攔”
  3. 操作三同理;
  4. 更新單調隊列來維護即可
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define pii pair<int,int>
typedef long long ll;
const int mod=1e9+7;
const int M=1e6+6;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
int h[M],dp[M],f[M],down[M],up[M];
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&h[i]);
    down[1]=1,up[1]=1;
    int totd=1,totu=1;

    memset(f,0x3f,sizeof(f));
    f[1]=0;
    for(int i=2;i<=n;i++){
        while(totd>0&&h[i]>h[down[totd]])
            f[i]=min(f[i],f[down[totd--]]+1);
        while(totu>0&&h[i]<h[up[totu]])
            f[i]=min(f[i],f[up[totu--]]+1);
        f[i]=min(f[i],f[down[totd]]+1);
        f[i]=min(f[i],f[up[totu]]+1);
        if(h[down[totd]]==h[i])
            totd--;
        if(h[up[totu]]==h[i])
            totu--;
        down[++totd]=i;
        up[++totu]=i;
    }
    printf("%d",f[n]);
    return 0;
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM