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;
    }
    
  • 相关阅读:
    算法训练(大富翁)
    算法训练题(奖励最小)
    算法训练题
    乔布斯
    算法题(符合题意的6位数)
    算法题(八皇后)
    算法题(分小组)
    汉诺塔
    递归算法题(兔子)
    字符串-mask-每个元音包含偶数次的最长子字符串
  • 原文地址:https://www.cnblogs.com/mollnn/p/13842005.html
Copyright © 2011-2022 走看看