码迷,mamicode.com
首页 > 其他好文 > 详细

Histogram LightOJ - 1083

时间:2017-10-21 16:28:12      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:names   正方形   pre   div   lan   依次   code   kmp   algorithm   

Histogram LightOJ - 1083

题意:给出一个直方图,由n个长条组成,它们的x轴上坐标分别为1-n,读入n之后读入的一行中,第i个表示x轴上坐标为i的长条长度。求直方图最大的正方形面积。

方法:

核心是求出每个长条向左右可以"扩展"的最大长度。

法一:单调栈

将n个元素的编号依次入栈。每次入栈前,设要入栈的编号为x,对应长度为l,将栈顶的编号对应的长度大于等于l的所有编号出栈(由于此题的一些特性,将“大于等于”改为“大于”也可以使用,但这不是标准的单调栈)。这之后,栈顶元素就是x能扩展到的最左端的端点减1(注意,是减1)。对于某个元素,其出栈的那一刻,使其出栈的x减一就是其能扩展到的最右侧的端点。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int T,n,ans,len;
 5 int st[30100],a[30100],l[30100],r[30100];
 6 void push(int idx)
 7 {
 8     while(len>0&&a[st[len]]>a[idx])    r[st[len--]]=idx-1;
 9     l[idx]=st[len];
10     st[++len]=idx;
11 }
12 int main()
13 {
14     int i,TT;
15     scanf("%d",&T);
16     for(TT=1;TT<=T;TT++)
17     {
18         scanf("%d",&n);
19         for(i=1;i<=n;i++)
20             scanf("%d",&a[i]);
21         len=0;
22         ans=0;
23         for(i=1;i<=n;i++)
24             push(i);
25         while(len>0)    r[st[len--]]=n;
26         for(i=1;i<=n;i++)
27             ans=max(ans,a[i]*(r[i]-l[i]));
28         printf("Case %d: %d\n",TT,ans);
29     }
30     return 0;
31 }

法二:奇奇怪怪的方法,类似链表/kmp的预处理

left[i]和right[i]分别表示能扩展到的最左/右侧的高度小于等于它的长条的编号。看起来可能很慢,但是实际上均摊复杂度O(n)。

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 int T,n,ans;
 5 int a[30100],left[30100],right[30100];
 6 int main()
 7 {
 8     int TT,i;
 9     scanf("%d",&T);
10     for(TT=1;TT<=T;TT++)
11     {
12         ans=0;
13         scanf("%d",&n);
14         for(i=1;i<=n;i++)
15             scanf("%d",&a[i]);
16         for(i=1;i<=n;i++)
17         {
18             left[i]=i;
19             while(left[i]>1&&a[left[i]-1]>=a[i])    left[i]=left[left[i]-1];
20         }
21         for(i=n;i>=1;i--)
22         {
23             right[i]=i;
24             while(right[i]<n&&a[right[i]+1]>=a[i])    right[i]=right[right[i]+1];
25         }
26         for(i=1;i<=n;i++)
27             ans=max(ans,a[i]*(right[i]-left[i]+1));
28         printf("Case %d: %d\n",TT,ans);
29     }
30 }

 

Histogram LightOJ - 1083

标签:names   正方形   pre   div   lan   依次   code   kmp   algorithm   

原文地址:http://www.cnblogs.com/hehe54321/p/loj-1083.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!