hdu 1506 单调栈问题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1506

题目的意思其实就是要找到一个尽可能大的矩形来完全覆盖这个矩形下的所有柱子,只能覆盖柱子,不能留空。

我们求得的面积其实就是Max{s=(right[i] - left[i] + 1)*height[i];(i>=1&&i<=n)}

每一个柱子都要尽可能向左向右延伸,使得获得最大的面积。

此时我就要用到单调栈

 

单调栈就是栈内元素单调递增或者单调递减的栈,单调栈只能在栈顶操作。

http://blog.csdn.net/liujian20150808/article/details/50752861

 

这里我们还是做一个总结

单调栈的维护是 O(n) 级的时间复杂度,因为所有元素只会进入栈一次,并且出栈后再也不会进栈了。

单调栈的性质:

1.单调栈里的元素具有单调性

2.元素加入栈前,会在栈顶端把破坏栈单调性的元素都删除

3.使用单调栈可以找到元素向左遍历第一个比他小的元素,也可以找到元素向左遍历第一个比他大的元素。

基于此题,我们可以知道,先每一次从左到右放入柱子(保持递增单调栈),也就说一旦有一个柱子和栈顶元素一比发现比它大,那么这个柱子首先要记录它的left值为自己的本身的下标,如果发现这个柱子比栈顶的小,我们依次将栈顶元素出栈,直至又能组成递增的序列,此时这个柱子的left值就为现在栈顶的left值。

后面我们从右向左放入柱子(保持的依旧是递增的单调栈)。获得right值。

代码如下

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<stack>
  5 #define LL long long
  6 using namespace std;
  7 const int MAXN = 100005;
  8 struct node
  9 {
 10     LL height;
 11     int left;
 12     int right;
 13     int index;
 14 };
 15 node nd[MAXN];
 16 int n;
 17 stack <node> st;//定义一个单调栈
 18 void clr()
 19 {
 20     while(!st.empty())
 21         st.pop();
 22 }
 23 LL work()
 24 {
 25     clr();
 26     for(int i = 1;i<=n;i++)
 27     {
 28         if(st.empty())
 29         {
 30             nd[i].left = i;
 31             st.push(nd[i]);
 32         }
 33         else
 34         {
 35             node td = st.top();
 36             if(td.height<nd[i].height)
 37             {
 38                 nd[i].left = i;
 39                 st.push(nd[i]);
 40             }
 41             else
 42             {
 43                 bool flag=false;
 44                 int c;
 45                 while(!st.empty())
 46                 {
 47                     if((st.top()).height>=nd[i].height)
 48                     {
 49                         c = (st.top()).left;
 50                         st.pop();
 51                     }
 52                     else
 53                     {
 54                         nd[i].left = c;
 55                         flag =true;
 56                         st.push(nd[i]);
 57                         break;
 58                     }
 59                 }
 60                 if(flag == false)
 61                 {
 62                     nd[i].left = c;
 63                     st.push(nd[i]);
 64                 }
 65             }
 66         }
 67     }
 68     clr();
 69     for(int i = n;i>=1;i--)
 70     {
 71         if(st.empty())
 72         {
 73             nd[i].right = i;
 74             st.push(nd[i]);
 75         }
 76         else
 77         {
 78             node td = st.top();
 79             if(td.height<nd[i].height)
 80             {
 81                 nd[i].right = i;
 82                 st.push(nd[i]);
 83             }
 84             else
 85             {
 86                 bool flag=false;
 87                 int c;
 88                 while(!st.empty())
 89                 {
 90                     if((st.top()).height>=nd[i].height)
 91                     {
 92                         c = (st.top()).right;
 93                         st.pop();
 94                     }
 95                     else
 96                     {
 97                         nd[i].right = c;
 98                         st.push(nd[i]);
 99                         flag = true;
100                         break;
101                     }
102                 }
103                 if(flag == false)
104                 {
105                     nd[i].right = c;
106                     st.push(nd[i]);
107                 }
108             }
109         }
110     }
111     LL maxs = 0;
112     LL s;
113     for(int i = 1;i<=n;i++)
114     {
115         s = (nd[i].right - nd[i].left + 1)*nd[i].height;
116         if(maxs<s)
117             maxs = s;
118     }
119     return maxs;
120 }
121 int main()
122 {
123     while(~scanf("%d",&n))
124     {
125         if(n==0)
126             break;
127         for(int i = 1;i<=n;i++)
128         {
129             nd[i].index = i;
130             scanf("%I64d",&nd[i].height);
131         }
132         cout<<work()<<endl;
133     }
134     return 0;
135 }

 

posted @ 2016-03-19 15:22  fancy_boy  阅读(1825)  评论(0编辑  收藏  举报