zoukankan      html  css  js  c++  java
  • [CF1407D] Discrete Centrifugal Jumps

    Description

    给定一个序列,每次可以从 (i) 跳到 (j (>i)) 当且仅当满足以下三个条件之一:

    • (i+1=j)

    • (max(h[i+1,j-1])<min(h_i,h_j))

    • (min(h[i+1,j-1])>max(h_i,h_j))

    求从下标为 (1) 的位置跳到下标为 (n) 的位置花费的最小步数。

    Solution

    考虑 dp,设 (f_i) 表示跳到第 (i) 个格子的最小步数,那么很显然 (f_i) 序列一定是单调的,这是由第一个转移条件保证的。

    先考虑第二个条件,分析 (i) 状态可以从哪些状态转移过来。

    维护一个单调递减的栈,那么有且仅有加入 (i) 的弹栈过程中经历的所有栈顶是合法的 (j)

    所以我们只需要在加入 (i) 的过程中,对每次弹栈后的栈顶 (j),做一次 (j o i) 的转移即可。

    对第三个条件也是同理的。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    int n;
    int a[N],f[N];
    int staAsc[N],topAsc,staDec[N],topDec;
    
    signed main()
    {
        cin>>n;
        for(int i=1;i<=n;i++) cin>>a[i];
    
        f[0]=1e9;
        f[1]=0;
    
        staAsc[++topAsc]=1;
        staDec[++topDec]=1;
    
        for(int i=2;i<=n;i++)
        {
            f[i]=f[i-1]+1;
    
            while(topAsc && a[staAsc[topAsc]]>=a[i])
            {
                --topAsc;
                if(a[staAsc[topAsc+1]]==a[i]) continue;
                f[i]=min(f[i], f[staAsc[topAsc]]+1);
            }
            staAsc[++topAsc]=i;
    
            while(topDec && a[staDec[topDec]]<=a[i])
            {
                --topDec;
                if(a[staDec[topDec+1]]==a[i]) continue;
                f[i]=min(f[i], f[staDec[topDec]]+1);
            }
            staDec[++topDec]=i;
        }
        
        cout<<f[n]<<endl;
        return 0;
    }
    
  • 相关阅读:
    go函数和方法
    Golang的“面向对象”
    高性能 socket 框架
    wpf 自定义圆形按钮
    WPF 实际国际化多语言界面
    使用过滤器对mvc api接口安全加密
    使用mvc3实现ajax跨域
    WPF,给颜色SolidColorBrush添加动画
    C# 通用验证类 支持 WPF,MVC,Winform
    WSL安装ubuntu搭建vue开发环境(三):docker安装
  • 原文地址:https://www.cnblogs.com/mollnn/p/13842005.html
Copyright © 2011-2022 走看看