单调栈学习+例题:小c的数学问题

本文介绍了一种利用单调栈解决特定区间问题的方法。通过构造左右区间,求解给定序列中具有最大区间价值(区间和乘以区间内最小值)的区间。文章详细解释了算法流程,并提供了一个具体示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单调栈:

             字面意思就是一个结构栈其中的元素是单调的(严格递增或递减)

             对于一个新元素的加入,会把栈顶所有破坏单调性的元素给“弹走”,例如:【7,5,3,新加入一个元素5,会把原栈中的5,3“弹走”,这时形成新的栈为【7,5

用途:

  1. 最基础的应用就是给定一组数,针对每个数,寻找它和它右边第一个比它大的数之间有多少个数。
  2. 给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列的长度最大。
  3. 给定一序列,寻找某一子序列,使得子序列中的最小值乘以子序列所有元素和最大

 

       通常来讲,单调栈更倾向于一维数组的问题,或者是多维数组可以转化为一维数组的问题。多存储元素坐标而非元素值。

       问题多见于寻找数组元素左区间或右区间最大最小问题,或者找出元素的两边界问题。
                 

 

 


问题 J: 小C的数学问题

 

时间限制: 1 Sec  内存限制: 128 MB
提交: 596  解决: 150
[提交] [状态] [命题人:外部导入]

题目描述

小C是个云南中医学院的大一新生,在某个星期二,他的高数老师扔给了他一个问题。

让他在1天的时间内给出答案。

但是小C不会这问题,现在他来请教你。

请你帮他解决这个问题。

有n个数,每个数有权值。

数学老师定义了区间价值为区间和乘上区间内的最小值。

现在要你找出有最大区间价值的区间是什么,并输出区间价值。

 

输入

每个输入文件只包含单组数据。
第一行一个整数n。(1 <= n <= 100000)
第二行n个整数a_1,a_2,...,a_n。(0 <= a_i <= 1000000)

 

输出

第一行输出一个整数,表示最大的区间价值。
第二行输出两个整数,表示区间的起点和终点。
保证答案唯一。

 

样例输入

复制样例数据

6
10 1 9 4 5 9

样例输出

108
3 6

题解:题意很简单,就是求出最大的【区间最小值乘上区间和】,当然用到了前缀和的知识

 

#include<bits/stdc++.h>
const double PI=acos(-1);
const int INF=1e9+7;
const int xmax=1e6+7;
const int xmin=-1e6+7;
typedef long long ll;
using namespace std;


int n,a[xmax];
ll sum[xmax];       ///前缀和
int l[xmax];       ///左区间
int r[xmax];        ///右区间
ll ans,L,R;

int main()
{
    scanf("%d",&n);

    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];   ///前i项的前缀和
    }

    for(int i=1;i<=n;i++){      ///找i的左区间
        int j=i;
        while(j>1&&a[j-1]>a[i]){j=l[j-1];}
        l[i]=j;
    }

    for(int i=n;i;i--){         ///找i的右区间
        int j=i;
        while(j<n&&a[j+1]>=a[i]){j=r[j+1];}
        r[i]=j;
    }
    ///以上两个for循环找的是对每一个i来说,i作为一个区间的最小值的【l[i],r[i]】区间

    ans=-1;
    for(int i=1;i<=n;i++){
        ///遍历每一个以i为最小值的区间,求出最大值
        ll t=a[i]*(sum[r[i]]-sum[l[i]-1]);
        if(t>ans){
            ans=t;
            L=l[i];
            R=r[i];
        }
    }

    printf("%lld\n%lld %lld\n",ans,L,R);

    return 0;
}

 

 


以下是学习单调栈过程中。借鉴或引用了一些结论的博客

https://blog.youkuaiyun.com/zuzhiang/article/details/78134247

https://blog.youkuaiyun.com/renzijing/article/details/89024366

https://www.cnblogs.com/Atanisi/p/7563178.html

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值