Description
Input
Output
Sample Input
6 3 1 6 4 5 2
Sample Output
603 5
这题是用单调栈,题意是给你一段区间,求出(在这段区间之类的最小值*这段区间所有元素之和)的最大值。可以维护一个单调递增队列,记录栈内的sum(区间所有元素的和),minmum(区间最小值),begin(区间的最前面一个数的位置),count(区间的长度)。每读入一个数,把栈内所有大于等于它的数都删掉,这里删掉的时候注意要把删掉的数所对应的区间的长度以及和传到栈内下面的一个数所对应的区间,因为这个数要比下面的数大,所以对下面那个数来说,删掉的数所对应的区间也可以包含进来。当所有的数都循环完后,再从栈顶开始向下删除数,同时把这个数的信息传到下一个数,可以发现两个操作在这里是一样的。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<algorithm> using namespace std; #define maxn 100060 #define ll long long struct node{ ll sum,minmum,begin,count; }stack[maxn]; int main() { //int n,m,i,j,top; int n,m,i,j; ll ans,sum1,tmp,count,a,ansbegin,ansend,top; while(scanf("%d",&n)!=EOF) { ansbegin=ansend=1; top=0;ans=0; for(i=1;i<=n;i++){ scanf("%lld",&a); sum1=0;count=tmp=0; while(top>0 && stack[top].minmum>=a){ stack[top].count+=count; count=stack[top].count; stack[top].sum+=tmp; tmp=stack[top].sum; sum1=stack[top].sum*stack[top].minmum; if(ans<sum1){ ans=sum1; ansbegin=stack[top].begin; ansend=stack[top].begin+stack[top].count-1; } top--; } top++; stack[top].sum=a+tmp; stack[top].minmum=a; stack[top].count=count+1; stack[top].begin=i-stack[top].count+1; } sum1=0;count=tmp=0; while(top>0){ stack[top].count+=count; count=stack[top].count; stack[top].sum+=tmp; tmp=stack[top].sum; sum1=stack[top].sum*stack[top].minmum; if(ans<sum1){ ans=sum1; ansbegin=stack[top].begin; ansend=stack[top].begin+stack[top].count-1; } top--; } printf("%lld\n%lld %lld\n",ans,ansbegin,ansend); } }这题也可以用单调队列,其实单调队列更加好写,不容易写错,先从左到右建立一个严格单调递增的单调队列,计算出每一个数的左边界l[i],表示以这个数为最小值的区间,向左最多扩展的距离,同理可以得到r[i].#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; typedef long long ll; #define inf 0x7fffffff #define maxn 100050 ll a[maxn]; ll l[maxn],r[maxn]; ll sum[maxn]; ll q[1111111][2]; int main() { int n,m,i,j,T; int front,rear; while(scanf("%d",&n)!=EOF) { sum[0]=0; for(i=1;i<=n;i++){ scanf("%lld",&a[i]); sum[i]=sum[i-1]+a[i]; } front=1;rear=0; for(i=1;i<=n;i++){ while(front<=rear && q[rear][0]>=a[i]){ rear--; } if(front>rear)l[i]=1; else{ l[i]=q[rear][1]+1; } rear++; q[rear][0]=a[i];q[rear][1]=i; } front=1;rear=0; for(i=n;i>=1;i--){ while(front<=rear && q[rear][0]>=a[i]){ rear--; } if(front>rear)r[i]=n; else{ r[i]=q[rear][1]-1; } rear++; q[rear][0]=a[i];q[rear][1]=i; } ll num=0; ll ll,rr; for(i=1;i<=n;i++){ if(a[i]*(sum[r[i] ]-sum[l[i]-1 ] )>=num){ ll=l[i];rr=r[i]; num=a[i]*(sum[r[i] ]-sum[l[i]-1 ] ); } } printf("%lld\n",num); printf("%lld %lld\n",ll,rr); } return 0; }