题目链接:https://ac.nowcoder.com/acm/contest/549/H
题意:给一个柱状图,包括每个矩阵的宽度和高度,求能组成的最大矩阵的面积。
思路:显然最大矩阵的高一定为n个矩阵中的一个矩阵的高,所以不访用单调栈求出每个矩阵左边、右边第一个高度小于该矩阵的下标。然后用树状数组求出该区间的宽度和,遍历一遍即可得到结果。算法复杂度O(nlogn),顺便吐槽这题数据,一朋友没用单调栈暴力求区间,复杂度为O(n^2),竟然也过了。。
AC代码:
#include<cstdio> using namespace std; typedef long long LL; const int maxn=1000005; int n,p; int h[maxn],stk[maxn],L[maxn],R[maxn]; LL tr[maxn],ans; int lowbit(int x){ return x&(-x); } void update(int x,int num){ while(x<=n){ tr[x]+=num; x+=lowbit(x); } } int query(int x){ int ans=0; while(x>0){ ans+=tr[x]; x-=lowbit(x); } return ans; } int main(){ scanf("%d",&n); for(int i=1;i<=n;++i){ int tmp; scanf("%d",&tmp); update(i,tmp); } for(int i=1;i<=n;++i) scanf("%d",&h[i]); h[0]=h[n+1]=0; stk[p=0]=0; for(int i=1;i<=n;++i){ while(h[stk[p]]>=h[i]) --p; L[i]=stk[p]+1; stk[++p]=i; } stk[p=0]=n+1; for(int i=n;i>=1;--i){ while(h[stk[p]]>=h[i]) --p; R[i]=stk[p]-1; stk[++p]=i; } for(int i=1;i<=n;++i){ int w=query(R[i])-query(L[i]-1); if(1LL*w*h[i]>ans) ans=1LL*w*h[i]; } printf("%lld ",ans); return 0; }