• 洛谷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;
    }
    顺风不浪,逆风不怂。
  • 相关阅读:
    初學C#窗口事件
    Visual Studio 2005.net 代码段(Snippet)丢失的解决方案
    使用C#代码段,提高工作效率(C# code snippet)
    同时拥有静态IP和动态IP
    让XP启动时不加载Autoexec.bat
    C#中构造函数和析构函数的用法
    C# 輸入關鍵字後按Tab鍵無法帶出相關內容
    C# 打開文件
    system.net.mail 與system.web.mail的區別
    C#中的建立事件
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9872909.html
Copyright © 2020-2023  润新知