zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    js检测对象中是否存在某个属性
    ES6 笔记
    DataSet 用法
    CommandBehavior.CloseConnection有何作用
    SqlDataReader
    Listview.Finditem()函数用法
    Instr()函数用法
    StringBuilder与StringBuffer的区别
    [DllImport("kernel32.dll")]使用
    extern用法
  • 原文地址:https://www.cnblogs.com/starve/p/13638360.html
Copyright © 2011-2022 走看看