標籤:style blog http color io ar for sp div
VJ題目連結
題意:
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 100010int 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\n",ans); printf("%d %d\n", lans, rans); } return 0;}
UVALive 3517:Feel Good(單調棧 Grade C)