单调栈模型图解入门(HDU1506)

HDU  1506 面积合并

http://acm.hdu.edu.cn/showproblem.php?pid=1506


很经典的一个题目了。


保持栈非严格单调递增。  



  4号节点来的时候,  3号节点已经无法向右扩展。

 1 、则3号的生命周期结束。  以3号节点高度为矩阵长的 宽度为 (4-3) 。

 2 、同时2号的生命周期结束。  以2号节点高度为矩阵长的 宽度为 (4-2)  ,

        因为2号可以向右扩展到4号的左边。




  2、3节点已死。

 也就是说4号节点可以向左扩展到2号节点,则当4号节点入栈的时候,向左扩展节点标记为2。



5号节点来了。

4号节点无法向右扩展,则4号节点生命周期结束。

以4号节点高度为矩阵长的 宽度为 (5-2)  。

也就是说5号节点可以向左扩展到2(就是4号节点扩展的地方) 。



1号节点无法向右扩展,则1号节点生命周期结束。

以1号节点高度为矩阵长的 宽度为 (5-1)  。

也就是说5号节点可以向左扩展到1(就是1号节点扩展的地方) 。



const int Max_N = 100008 ;

typedef __int64 LL ;

struct  Elem{
        int  id ;  //向左扩展最远的下标
        LL  height ; //当前节点高度
        Elem(){}
        Elem(int _id , LL _height):id(_id) , height(_height){}
};

struct Stack{
       Elem elem[Max_N] ;
       int  top ;
       Stack(){
           top = -1 ;
       }
       void Pop(){
            top-- ;
       }
       bool Empty(){
            return top == -1 ;
       }
       void Push(Elem e){
            elem[++top] = e ;
       }
       Elem Top(){
            return elem[top] ;
       }
};

LL   x[Max_N] ;
int  N ;

LL   Ans(){
     int i , L_id ;
     LL ans = 0 ;
     Elem e ;
     Stack stk ;
     for(i = 0 ; i <= N ; i++){
            L_id = i ;
            while(! stk.Empty() && stk.Top().height > x[i]){
                  ans = max(ans  , (LL)(i - stk.Top().id) * stk.Top().height ) ;
                  L_id = stk.Top().id ;
                  stk.Pop() ;
            }
            stk.Push(Elem(L_id , x[i])) ;
     }
     return ans ;
}


int  main(){
     int i ;
     while(cin>> N && N){
          for(i = 0 ; i < N ; i++)
              scanf("%I64d" ,&x[i]) ;
          x[N] = -1 ;
          cout<<Ans()<<endl  ;
     }
     return 0 ;
}


POJ 3250 

http://poj.org/problem?id=3250

一排共n头牛排队站在一起,给出队伍中每头牛的高度。每头牛只能看到站在他右边且个头比他小的牛。求出所有牛可以看到的牛数之和。

单调栈,严格单调递减。

typedef long long LL  ;

const int Max_N = 100008 ;

int   x[Max_N] ;

struct Elem{
       int id ;
       int height ;
       Elem(){}
       Elem(int _id , int _height):id(_id) , height(_height){}
};


class  Stack{
       private  :
          int  top  ;
          Elem elem[Max_N] ;
       public  :
          Stack(){
               top = -1 ;
          }
          bool Empty(){
               return top == -1 ;
          }
          Elem Top(){
               return elem[top] ;
          }
          void Push(Elem e){
               elem[++top] = e ;
          }
          void Pop(){
               --top ;
          }
};

int  N ;

LL   Ans(){
     LL ans = 0 ;
     int i  ;
     Stack stk ;
     for(i = 1 ; i <= N ; i++){
          while(! stk.Empty() && stk.Top().height <= x[i]){
               ans += (LL)(i - stk.Top().id - 1) ;
               stk.Pop() ;
          }
          stk.Push(Elem(i , x[i])) ;
     }
     return ans ;
}

int  main(){
     int i ;
     while(cin>> N){
           for(i = 1 ; i <= N ; i++)
               scanf("%d" , &x[i]) ;
           x[N+1] = 1<<30 ;
           N++ ;
           cout<<Ans()<<endl ;
     }
     return 0 ;
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值