poj 2796

poj 2796


原题

题意:

给定一个长度为 n(n<105) 的非负整数序列 a ,定义函数f(l,r)=(minri=la[i])(ri=la[i]),求 f(l,r) 的最大值及其对应的 l r

思路:

对于 ri=l(a[i]) 可以通过前缀和相减 O(1) 得到。
当最小值 a[i] 确定时,由于序列 a 是非负整数序列,区间越大sum值越大,故我们希望在保证 a[i] 是区间最小值的同时使得区间长度 rl+1 尽可能大,这里可以用单调栈处理。
枚举每个点为区间最小值,取所有情况的最大值,复杂度 O(n)
注意答案会爆int。

单调栈:

# include<stdio.h>

const int NMax=100000;
int n, ansL, ansR, in[NMax+1], range[NMax+1][2];
long long sum[NMax+1], ans;

struct Stack{
    int id[NMax+1];
    int top;
    void Init(){top=0;}
    void Pop(){top--;}
    void Push(int i){id[top++]=i;}
    bool Empty(){return top==0;}
    int Head(){return id[top-1];}
}sta;

int main(){
    int i;
    scanf("%d", &n);
    ans=(1<<31);
    sum[0]=0;
    sta.Init();
    for(int i=1; i<=n; i++){
        scanf("%d", in+i);
        sum[i]=sum[i-1]+in[i];
    }
    for(int i=1; i<=n; i++){
        while(!sta.Empty() && in[sta.Head()]>=in[i]){
            range[sta.Head()][1]=i-1;
            sta.Pop();
        }
        range[i][0]=sta.Empty()?1:sta.Head()+1;
        sta.Push(i);
    }
    while(!sta.Empty()){
        range[sta.Head()][1]=n;
        sta.Pop();
    }
    for(int i=1; i<=n; i++){
        long long tans;
        tans=(sum[range[i][1]]-sum[range[i][0]-1])*in[i];
        if(tans>ans){
           ans=tans;
           ansL=range[i][0];
           ansR=range[i][1];
        }
    }
    printf("%lld\n%d %d\n", ans, ansL, ansR);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值