POJ 2769

http://poj.org/problem?id=2796

题意:求n个数的和乘以这n个数中的最小值的积最大的数,以及其范围。

思路:求每一个数两边的比其大的数的和,再乘以这个数。还有一个范围,用单调栈找以及记录。

这个题和2559差不多,就是多了一个对数字的求和。

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 #include <stack>
 4 
 5 #define x 100010
 6 
 7 using namespace std;
 8 
 9 stack<long long >s;
10 long long l[x],r[x],a[x],sum,ans,z[x],m,loc;
11 
12 int main(){
13     int n;
14     scanf("%d",&n);
15     ans=0;
16     z[0]=0,r[0]=1,l[0]=1,l[1]=1,r[n]=n;     //要考虑案例是1 0 的情况。
17     for(int i=1;i<=n;i++){
18 
19         scanf("%lld",&a[i]);
20         z[i]+=z[i-1]+a[i];       //z[m]-z[n-1]就是从m到n的a[i]之和。
21     }
22     a[0]=-1,a[n+1]=-1;
23     while(!s.empty()){
24 
25         s.pop();
26     }
27         s.push(0);
28 
29     for(int i=1;i<=n;i++){
30 
31         for(m=s.top();a[m]>=a[i];m=s.top())
32 
33             s.pop();
34 
35             l[i]=m+1;
36 
37             s.push(i);
38     }
39     while(!s.empty())
40 
41         s.pop();
42 
43     s.push(n+1);
44 
45     for(int i=n;i>0;i--){
46             sum=0;
47 
48         for(m=s.top();a[m]>=a[i];m=s.top())
49             s.pop();
50         r[i]=m-1;
51         s.push(i);
52         if((z[r[i]]-z[l[i]-1])*a[i]>ans) {ans=(z[r[i]]-z[l[i]-1])*a[i];loc=i;}
53     }
54 
55     printf("%lld\n%lld %lld\n",ans,l[loc],r[loc]);
56    return 0;
57 }

 

posted @ 2016-07-24 21:00  一个_小菜鸟  阅读(260)  评论(0编辑  收藏  举报