最近做这方面的题很多,感觉单调栈很是神奇,通过维护一个单调不减的栈,遇到小于栈顶的栈顶元素便出栈,此时跟新结果。
这个比RMQ的ST算法要快很多,ST算法要枚举每一个区间(没想到其他做法,可能要dp,反正不会)。这个题关键在于给每一个点找一个最长子序列,使其最小值为其本身,这样扫一遍得到结果。而单调栈正好可以解决这个问题。
(这个题大家注意要用long long我被int卡死,干脆全换long long了.......)
#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
using namespace std;
struct point{
long long l,r;
long long h;
long long sum;
}stack[100005];
int main(){
long long n,i;
long long curw,curh;
scanf("%lld",&n);
{
long long lasth=0,top=0;
long long l,r;
long long ans=-1;
for(i=1;i<=n;i++){
scanf("%lld",&curh);
if(curh>=lasth){
stack[top].l=stack[top].r=i;
stack[top].sum=curh;
stack[top].h=curh;
top++;
}
else{
long long totw=0, rr=stack[top-1].r,min;
while(top>0){
if(stack[top-1].h>curh){
min=stack[top-1].h;
if((totw+stack[top-1].sum)*min>ans){
ans=(totw+stack[top-1].sum)*min;
l=stack[top-1].l;
r=rr;
}
totw+=stack[top-1].sum;
top--;
}
else
break;
}
stack[top].h=curh;
stack[top].sum=curh+totw;
stack[top].l=stack[top].l;
stack[top].r=i;
top++;
}
lasth=stack[top-1].h;
}
long long totw=0, rr=stack[top-1].r ,min;
while(top>0){
min= stack[top-1].h;
if((totw+stack[top-1].sum)*min>ans){
ans=(totw+stack[top-1].sum)*min;
l=stack[top-1].l;
r=rr;
}
totw+=stack[top-1].sum;
top--;
}
printf("%lld\n%lld %lld\n",ans,l,r);
}
}