单调栈应用

 1 /*
 2   题意:POJ2796 给定一个长度为n的数组,求sum(a[i])*min(a[i)最大的一段区间。
 3   思路:枚举每个a[i],求最左边和最右边的距离。利用单调栈求左右区间
 4   时间:2018.07.17
 5 */
 6 // #include <bits/stdc++.h>
 7 #include <cstdio>
 8 #include <iostream>
 9 using namespace std;
10 
11 typedef long long LL;
12 const int MAXN=100005;
13 const LL MOD7 = 1e9+7;
14 
15 int a[MAXN];
16 int n;
17 LL sum[MAXN];
18 int L[MAXN];
19 int R[MAXN];
20 int Stack[MAXN];
21 int top;
22 
23 void printStack()
24 {
25     for (int i=0;i<top;++i) printf("%d ",Stack[i]);printf("\n");
26 }
27 
28 void init()
29 {
30     top=0;
31     for (int i=1;i<=n;++i)
32     {
33         while (top && a[Stack[top-1]]>=a[i]) --top;
34         // printf("%d: ",i);
35         // printStack();
36         if (!top) L[i]=1;
37         else L[i]=Stack[top-1]+1;
38         Stack[top++]=i;
39     }
40     top=0;
41     for (int i=n;i>=1;--i)
42     {
43         while (top && a[Stack[top-1]]>a[i]) --top;
44         if (!top) R[i]=n;
45         else R[i] = Stack[top-1]-1;
46         Stack[top++]=i;
47     }
48     // for (int i=1;i<=n;++i) printf("L[%d]=%d\tR[%d]=%d\n",i,L[i],i,R[i]);
49 }
50 
51 int main()
52 {
53 #ifndef ONLINE_JUDGE
54     freopen("test.txt","r",stdin);
55 #endif // ONLINE_JUDGE
56     scanf("%d",&n);
57     for (int i=1;i<=n;++i)
58     {
59         scanf("%d",&a[i]);
60         sum[i]=sum[i-1]+a[i];
61     }
62     init();
63     LL ans=-1;
64     int l,r;
65     for (int i=1;i<=n;++i)
66     {
67         LL tmp = (LL)a[i]*(sum[R[i]]-sum[L[i]-1]);
68         if (tmp>ans)
69         {
70             ans = tmp;
71             l=L[i];
72             r=R[i];
73         }
74     }
75     printf("%lld\n",ans);
76     printf("%d %d\n",l,r);
77     return 0;
78 }

 

转载于:https://www.cnblogs.com/LeeSongt/p/9326323.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值