题意:
一排数,找到一个区间,使得该区间内 所有数之和乘以该区间内的最小数 最大,输出该最大值和区间左右端点。
Sample Input
6
3 1 6 4 5 2
Sample Output
60
3 5
冉了我好久的一道单调栈的题,毕竟我也是刚入门。
注意的一点:ans初值要赋为-1,如果默认赋为0,当我们的数据最大值为0时就无法操作
代码如下:
#include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int MX=1e5+100; int n; long long a[MX],bit[MX],L[MX],R[MX],stk[MX],top; int lowbit(int x){ return x&-x; } void update(int x,int add) { for(;x<=n;x+=lowbit(x)) bit[x]+=add; } long long sum(int x) { long long tot=0; for(;x;x-=lowbit(x)) tot+=bit[x]; return tot; } void sol() { while(top>0) top--; for(int i=1;i<=n;++i) { while(top>0 && a[i]<=a[stk[top]]) top--; if(top==0) L[i]=0; else L[i]=stk[top]; stk[++top]=i; } while(top>0) top--; for(int i=n;i>=1;--i) { while(top>0 && a[i]<=a[stk[top]]) top--; if(top==0) R[i]=n+1; else R[i]=stk[top]; stk[++top]=i; } } long long bin(int l,int r) { return sum(r)-sum(l-1); } int main() { while(scanf("%d",&n)!=EOF) { memset(bit,0,sizeof(bit)); for(int i=1;i<=n;++i) { scanf("%d",&a[i]); update(i,a[i]); } sol(); long long ans=-1; int l,r; for(int i=1;i<=n;++i) { long long t=bin(L[i]+1,R[i]-1)*a[i]; if(t>ans) { ans=t; l=L[i]+1; r=R[i]-1; } } printf("%lld %d %d ",ans,l,r); } return 0; } /* 6 3 1 6 4 5 2 */