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 }