zoukankan      html  css  js  c++  java
  • 单调栈模板题 luogu P2659

    题目链接:https://www.luogu.org/problem/P2659

    实际上就是要我们求出每个数字左右两边第一个小于它的数字位置,然后两个位置所在的开区间长度乘以这个数字,取最大值输出。

    因为是求两边第一个小于a[i]的数字,所以我们弄一个递增(其实是不减小就可以了,可以有相同大小的元素)的单调栈,从栈底到栈顶的数字是依次增大的,在求的过程中要始终保持递增的性质。我们每次在数字入栈时求出数字左边第一个小于它的数字位置,在出栈的时候求出右边第一个小于它的数字位置,为什么是这样,看下面,我这里的栈保存的是元素下标,而不是元素值。

    L[i]记录左边第一个小于a[i]的元素位置(下标),没有就是0,R[i]记录右边第一个小于a[i]的元素位置,没有就是n+1。

      对于一个a[i],假如a[i]大于栈顶元素(我的栈存的是下标,我们比较是就拿这个下标的值比较),那么如果把a[i]压入栈顶,这个栈还是递增的,这个时候栈顶元素就是第一个小于a[i]的数字,我们直接把L[i]赋值为栈顶元素就行了。

      对于a[i]等于栈顶元素的情况,假如说值都是5好吧,那么其实栈顶的5在它入栈的时候,它的L数组值(它左边第一个小于它的元素位置)我们一定会先得到对吧,那么当前的a[i](也是5),它的L数组值肯定等于栈顶元素的L数组值吧,因为他俩相等,所以直接把a[i]的L数组值赋值为栈顶元素的数组值就可以了,在把a[i]入栈。

      假如a[i]小于栈顶元素,那么如果我们把a[i]压入栈中,那么这个栈里面的元素就不单调递增了,所以说我们需要把栈里面比a[i]大的元素都弹出,假如现在我们要弹出当前栈顶元素,那么其实现在a[i]就是栈顶元素右边的第一个小于栈顶元素的值,所以我们这个时候可以直接把R[s.top()]赋值为i,这样每当我们出栈一个元素,这个元素的左右两边第一个小于它的元素位置就都找到了(左边的在进栈就找到了)。

    然后,就没了。

    我自己写的板子,应该木有问题,就是慢了点,写的时候那个栈不是s,写成了q,不知道为什么:

    #include<iostream>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<stack>
    #include<cmath>
    #include<vector>
    #include<set>
    #include<cstdio>
    #include<string>
    #include<deque> 
    using namespace std;
    typedef long long LL;
    #define eps 1e-8
    #define INF 0x3f3f3f3f
    #define maxn 2000005
    stack<int>q;
    int n,m,k,t;
    int a[maxn];
    int L[maxn],R[maxn]; 
    inline int read(){
        int f=1,x=0;char ch;
        do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
        do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
        return f*x;
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        a[i]=read();
        for(int i=1;i<=n;i++){//线性扫一遍 
            while(!q.empty()&&a[q.top()]>a[i]){//先检查栈顶元素大于a[i]的情况
                int s=q.top();    //保存一下栈顶元素值(下标) 
                R[s]=i;            //得到栈顶元素右边第一个小于它的元素下标 
                q.pop();        //出栈 
            }
            
            if(q.empty())        //假如栈为空 
            L[i]=0;
            else if(a[q.top()]==a[i])    //假如栈顶元素等于a[i],那么L[i]就赋值为栈顶元素的L数组值 
            L[i]=L[q.top()];
            else                        //栈顶元素小于a[i],把a[i]入栈 
            L[i]=q.top();
            
            q.push(i);
        }
        while(!q.empty()){//最后栈顶可能还有元素没有出栈,这个时候他们的R数组值都是n+1,因为右边没有比他们小的值了 
            int s=q.top();
            R[s]=n+1;
            q.pop();
        }
        LL ans=0;
        for(int i=1;i<=n;i++)
        ans=max(ans,(LL)a[i]*(R[i]-L[i]-1)); 
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    财富平台项目日记1:spring boot + mybatis 实现分页查询
    Spring boot 跨域
    Mysql索引
    Java中list多对多拆分
    Redis持久化
    Windows下安装Redis
    idea 常用快捷键
    数据库事务
    Linux开启防火墙端口号
    nginx相关
  • 原文地址:https://www.cnblogs.com/6262369sss/p/11257259.html
Copyright © 2011-2022 走看看