zoukankan      html  css  js  c++  java
  • CF 1407D

    单调栈 + dp 

    dp蛮好想的

    单调栈需要注意,此题要求i由j转移而得的条件为:

    1. j == i - 1

    2. i, j位置的h较小值必须大于二者之间序列内的最大值

    3. i, j位置的h较大值必须小于二者之间序列内的最小值

    满足任意一条即可转移

    而 对于相同高度的元素,则不能同时出现在栈内。因为当后续节点由此部分节点进行转移时,相同高度的前一个元素是不能进行转移的。

    因而必须判断,当即将加入栈内的元素与栈顶元素高度相同时,则需要将i位置的dp更新,之后将原先的栈顶元素弹出,再将新的具有相同高度的i节点加入栈中。

    这也与栈的单调性保持了一致。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cmath>
     5 #include<stack>
     6 #include<cstdio>
     7 #define INF 0x3f3f3f3f
     8 using namespace std;
     9 const int N = 3e5 + 10;
    10 
    11 int n;
    12 int a[N];
    13 int dp[N];
    14 
    15 int read(){
    16     char ch=getchar();int x=0,f=1;
    17     while(ch<'0' || ch>'9')    {if(ch=='-')f=-1;ch=getchar();}
    18     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 stack<int> s1, s2;//up, down
    22 int main(){
    23     n = read();
    24     for(register int i = 1 ; i <= n ; i++){
    25         a[i] = read();
    26         dp[i] = INF;
    27     }
    28     dp[1] = 0;
    29     s1.push(1);
    30     s2.push(1);
    31     for(register int i = 2 ; i <= n ; i++){
    32         //递减栈 
    33         while(!s1.empty() && a[s1.top()] < a[i]){
    34             dp[i] = min(dp[i], dp[s1.top()] + 1);
    35             s1.pop();
    36         }
    37         if(int(s1.size())){    
    38             dp[i] = min(dp[i], dp[s1.top()] + 1);
    39             if(a[i] == a[s1.top()]){//严格保持栈的单调性    
    40                 s1.pop();
    41             //若存在两个相同高度的块,后更新dp实际上不可更新前一个高度  4 3 3 : i = 2 ?只能更新后面那个3    
    42             }
    43         }
    44         s1.push(i);
    45         
    46         //递增栈 
    47         while(!s2.empty() && a[s2.top()] > a[i]){
    48             dp[i] = min(dp[i], dp[s2.top()] + 1);
    49             s2.pop();
    50         }
    51         if(int(s2.size())){
    52             dp[i] = min(dp[i], dp[s2.top()] + 1);            
    53             if(a[i] == a[s2.top()]){
    54                 s2.pop();
    55             }
    56         }
    57         s2.push(i);
    58     }
    59     printf("%d
    ",dp[n]);
    60     
    61     return 0;
    62 }
  • 相关阅读:
    C 数组初始化
    Linux函数之snprintf()[一]
    出现一下错误
    IOS通过post方式发送图片续
    IOS通过post方式发送图片
    TCP和UDP的区别趣解
    [转]Release mode debugging with VC++
    [转]Math For Programmers
    OS:kernel and shell
    Reminder: 8020 rule
  • 原文地址:https://www.cnblogs.com/ecustlegendn324/p/13942095.html
Copyright © 2011-2022 走看看