题意:
有一个柱状图,有N条柱子。每一条柱子宽度都为1,长度为h1...hN。
在这N条柱子所构成的区域中找到一个最大面积,每平方米3块钱,问最多赚多少钱。
输入:
1<=N<=100000
0<=hi<=1000000000
思路:
N很大,肯定得用一个O(N)或O(NLOGN)的算法,,
假如这个面积的长是从第i条柱子到第j条柱子,宽则一定是第i条柱子到第j条柱子中最矮的那条柱子的高度。
而我们站在那根最矮的柱子向左看,第i-1条的柱子一定是小于当前柱子的,否则可以加进去。向右看同理。
所以了,咱们就枚举每一根柱子,把它当作一段区域中的最矮的那根,然后向左向右极大地去延伸。
具体如何延伸呢,
假设left[i]表示第i根向左最多延伸到的柱子编号
假设现在枚举到第k根柱子,如果第k-1根柱子高度小于本身,则向左没法延伸。如果大于等于,则从left[i-1]到i-1都是大于等于本身的,只需从left[i-1]-1开始继续往前比较,这里就可以用while循环实现了。
向右同理。
看代码,
代码:
int const N = 100005; int h[N], leftt[N], rightt[N]; int main(){ int n; while(cin>>n,n){ mem(leftt,0); mem(rightt,0); rep(i,1,n){ scanf("%d",&h[i]); leftt[i] = rightt[i] = i; } rep(i,2,n){ if(h[i]<=h[i-1]){ leftt[i] = leftt[i-1]; while(leftt[i]>1 && h[i]<=h[leftt[i]-1]){ leftt[i] = leftt[leftt[i]-1]; } } } rep2(i,n-1,1){ if(h[i]<=h[i+1]){ rightt[i] = rightt[i+1]; while(rightt[i]<n && h[i]<=h[rightt[i]+1]){ rightt[i] = rightt[rightt[i]+1]; } } } ll ans = 0; rep(i,1,n){ ll temp = (ll)(rightt[i]-leftt[i]+1)*(ll)h[i]; if(temp>ans) ans = temp; } printf("%I64d\n",ans); } return 0; }
时间: 2024-11-04 22:27:24