zoukankan      html  css  js  c++  java
  • 单调栈——POJ

    题目含义

    给出一堆数,要你在里面找几个相邻的数

    它们的和乘以它们的最小值是这所有数里最大的

    输出它们得到的值以及第一个数的坐标和最后一个数的坐标

    题目分析

    这个式子是:这些数的和 乘以 这些数的最小值

    那么如果最小值不变,数的个数是越多越好(因为数都大于零)

    那么我们可以考虑根据最小值划分区间,并按最小值从小到大排序

    这样的话ab相邻区间,a的最小值小于b的最小值

    当更新区间时,让b区间的和乘以b代表的最小值,得到b区间的值,与答案做比较,变为更大的那个

    再将b区间的范围融入a区间中,表示我们之后要算的是a区间的和乘以a表示的最小值

    注意将a[n+1]赋为-1,这样就能够更新总区间的值了

    题目代码

    #include<stdio.h>
    #include<iostream>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    const int maxn=1e5+7;
    int n,top,q[maxn],Left[maxn],ll,rr;
    LL a[maxn],sum[maxn],ans;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
        top=0,ans=-1;
        a[++n]=-1;
        for(int i=1;i<=n;i++){
            if(top==0||a[q[top]]<a[i]){
                q[++top]=i;
                Left[i]=i;///你需要一个数代表这个区间的第一个数的坐标
                continue;
            }
            if(a[i]==a[q[top]])continue;
            while(top>0&&a[q[top]]>a[i]){
                LL temp=(sum[i-1]-sum[Left[q[top]]-1])*a[q[top]];
                if(temp>ans){
                    ans=temp;
                    rr=i-1;
                    ll=Left[q[top]];
                }
                top--;
            }
    //        q[++top]=i;
            Left[i]=Left[q[++top]];
            q[top]=i;
        }
        printf("%lld
    %d %d
    ",ans,ll,rr);
        return 0;
    }
  • 相关阅读:
    二项式定理与组合恒等式
    「CEOI2020」象棋世界 题解
    矩阵 题解
    研一总结
    你明白transform中的skew属性是何如变换的吗?
    pip安装包
    Yaml中特殊符号"| > |+ |-"的作用
    使用ROOT用户运行Jenkins
    检查MySQL主从复制运行状态
    powerdesigner 怎么逆向生成 pdm文件
  • 原文地址:https://www.cnblogs.com/helman/p/11222359.html
Copyright © 2011-2022 走看看