广告印刷

来源:互联网 发布:广州谷得知乎 编辑:程序博客网 时间:2024/04/29 00:45

Description

最近,afy决定给TOJ印刷广告,广告牌是刷在城市的建筑物上的,城市里有紧靠着的N(N<=400000)个建筑。afy决定在上面找一块尽可能大的矩形放置广告牌。我们假设每个建筑物都有一个高度,从左到右给出每个建筑物的高度H1,H2…HN,0<Hi<=1,000,000并且我们假设每个建筑物的宽度均为1。要求输出广告牌的最大面积。

Input

第一行,一个整数N
第二行,N个空格间隔的整数,表示从左往右每栋楼的高度

Output

一个整数,表示最大面积

Sample Input

65 8 4 4 8 4

Sample Output

24

【分析】

        定义两个数组l[maxn],r[maxn]分别表示当前节点可以向左右扩展的最大长度。这个长度的要求是左边(右边)连续的不小于当前节点高度的最大区间长度。

        如样例的r便是:r[1]=2;r[2]=1;r[3]=4;r[4]=3;r[5]=1;r[6]=1;现在便是想怎样求得r和l数组。一个最朴素的想法便是枚举每个i然后往右边扫。显然时间复杂度为O(n^2)。不满足数据范围。

        可以用单调队列优化。从原序列中依次取出元素插入单调队列。若插入位置为tail,则需满足h[i]>=Q[tail-1]。若不满足,则tail向前移动,继续判断,直到满足为止。很明显,tail向前移动的过程,其实就是元素从队尾出队的过程。注意,在某个元素出队的同时,记下他的r值。用Qr数组记录Q数组中元素下标。那么,r[Qr[tail-1]]=i-Qr[tail-1]。这里i是当前要插入的元素下标,tail-1是要被删除的元素。

        最后,答案ans=max{(r[i]+l[i]-1)*h[i]};

 

【代码】
 

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<ctime>#include<iostream>#include<algorithm>using namespace std;const int maxn=500005;long long N,v[maxn],Q[maxn],Qr[maxn],t[maxn];long long l[maxn],r[maxn];long long ans=0;void _in(long long &x){char t=getchar();while(t<'0'||'9'<t) t=getchar();for(x=t-'0',t=getchar();'0'<=t&&t<='9';x=x*10+t-'0',t=getchar());}void _init(){_in(N);ans=0;for(int i=1;i<=N;i++)    _in(v[i]);}void _solve(){v[0]=-0x7FFFFFFF;v[N+1]=-0x7FFFFFFF;int head=1,tail=2;Q[head]=v[1];Qr[head]=1;for(int i=2;i<=N+1;i++){if(v[i]>=Q[tail-1]){Qr[tail]=i;    Q[tail++]=v[i];}else{while(v[i]<Q[tail-1]&&tail!=head){    tail--;    r[Qr[tail]]=i-Qr[tail];}Q[tail]=v[i];Qr[tail]=i;tail++;}}memset(Q,0,sizeof(Q));memset(Qr,0,sizeof(Qr));memcpy(t,v,sizeof(v));for(int i=0,j=N+1;i<=N+1;i++,j--)    v[i]=t[j];head=1,tail=2;Q[head]=v[1];Qr[head]=1;for(int i=2;i<=N+1;i++){if(v[i]>=Q[tail-1]){Qr[tail]=i;    Q[tail++]=v[i];}else{while(v[i]<Q[tail-1]&&tail!=head){    tail--;    l[Qr[tail]]=i-Qr[tail];}Q[tail]=v[i];Qr[tail]=i;tail++;}}memcpy(v,t,sizeof(t));memcpy(t,l,sizeof(l));for(int i=0,j=N+1;i<=N+1;i++,j--)    l[i]=t[j];for(int i=1;i<=N;i++){long long temp=(r[i]+l[i]-1)*v[i];ans=max(ans,temp);}printf("%I64d\n",ans);}int main(){    _init();_solve();return 0;}


原创粉丝点击