题意:
n个数,求区间[l,r] 使得 sum[l,r]*min(a[l],a[l+1],...,a[r]) 最大。若有多种答案,输出区间最短的。若还有多组,输出最先出现的。
思路:
求出a[i]为最小数时,最大的区间范围,即求a[i]的最左边的小于a[i]的位置,最右边的位置。
坑点:
因为要最小长度区间,当最小数是0的时候,就出现了巨大的坑点……所以特判。
代码:
#include <cstdio> #include <cstring> #include <cstdlib> #define N 100010 int a[N]; int l[N], r[N]; long long sum[N]; int n; int stk[N]; void getl() { int top = 0; for (int i = 1; i <= n; i++) { while (top > 0 && a[stk[top-1]] >= a[i]) top--; stk[top++] = i; if (top == 1) l[i] = 0; else l[i] = stk[top-2]; } } void getr() { int top = 0; for (int i = n; i > 0; i--) { while (top > 0 && a[stk[top-1]] >= a[i]) top--; stk[top++] = i; if (top == 1) r[i] = n+1; else r[i] = stk[top-2]; } } int main() { int isfirst = 0; while (scanf("%d", &n) != EOF) { if (isfirst++) puts(""); //!isfirst++?:puts(""); sum[0] = 0; for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); sum[i] = a[i] + sum[i-1]; } sum[n+1] = sum[n]; getl(); getr(); long long ans = -1; int lans, rans; for (int i = 1; i <= n; i++) { long long now = (sum[r[i]-1]-sum[l[i]])*a[i]; if (ans < now) { ans = now; lans = l[i]+1; rans = r[i]-1; //This is a Great 坑 if (ans == 0) { lans = i; rans = i; } //The Great 坑 End } else if (ans == now) { if (rans-lans+1 > r[i]-l[i]-1) { lans = l[i]+1; rans = r[i]-1; } } } printf("%lld ",ans); printf("%d %d ", lans, rans); } return 0; }