zoukankan      html  css  js  c++  java
  • 洛谷P2422 良好的感觉

    题目意思就是:最大化一个区间的和与这个区间的最小值的乘积。

    换一个角度看问题,如果我们穷举一个最小值 $ a_i $ ,然后往左右扩展,显然是对的,复杂度 $ O(n^2) $。所以我们要优化一下这个过程。

    首先扩展这个过程的原则就是所有加入这个区间的数都必须小于选定的最小值 $ a_i $,那么我们可以把这个过程换一个叙述方法,就是对于每个数我们分别往左右找到第一个比 $ a_i $ 小的数,编号分别记成 $ l_i $ 、 $ r_i $ ,则答案就是 $ sum(l_i+1,r_i-1) imes a_i​ $ 。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int maxn = 100005;
    
    inline int read(){
    	char ch = getchar();
    	int f = 1 , x = 0;
    	while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
    	return x * f;
    }
    
    int n,a[maxn];
    long long sum[maxn],f[maxn];
    int l[maxn],r[maxn];
    int stack[maxn],top;
    
    int main(){
    	n = read();
    	for(int i=1;i<=n;i++){
    		a[i] = read();
    		sum[i] = sum[i-1] + a[i];
    	}
    	top = 0;
    	for(int i=1;i<=n;i++){
    		while(top && a[stack[top]] > a[i])
    			r[stack[top--]] = i;
    		stack[++top] = i;
    	}
    	top = 0;
    	for(int i=n;i>0;i--){
    		while(top && a[stack[top]] > a[i])
    			l[stack[top--]] = i;
    		stack[++top] = i;
    	}
    	for(int i=1;i<=n;i++)
    		if(r[i] == 0)  r[i] = n + 1;
    	long long ans = 0;
    	for(int i=1;i<=n;i++)
    		ans = max(ans , (long long) a[i] * (sum[r[i] - 1] - sum[l[i]]));
    	printf("%lld
    ",ans);
    	return 0;
    }
    顺风不浪,逆风不怂。
  • 相关阅读:
    Ubuntu 下安装QT
    Ubuntu下配置Samba服务器
    二进制、八进制、十进制、十六进制之间转换
    Oracle_创建和管理表
    Oracle_数据处理
    单例模式
    01.DesignParttern设计模式,简单工厂,工厂方法,抽象工厂三大工厂的区别与联系
    MAC系统中的轻量级图像浏览器Lyn1.9
    MAC系统的绝佳截图工具Snipaste
    MAC系统的绝佳截图工具Snipaste
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9872909.html
Copyright © 2011-2022 走看看