2019 ICPC南昌邀请赛比赛 I. Max answer (单调栈+思维预处理)

Alice has a magic array. She suggests that the value of a interval is equal to the sum of the values in the interval, multiplied by the smallest value in the interval.

Now she is planning to find the max value of the intervals in her array. Can you help her?

Input

First line contains an integer n(1 \le n \le 5 \times 10 ^5n(1≤n≤5×105).

Second line contains nn integers represent the array a (-10^5 \le a_i \le 10^5)a(−105≤ai​≤105).

Output

One line contains an integer represent the answer of the array.

样例输入复制

5
1 2 3 4 5

样例输出复制

36 

                大意就是让你获取区间和*区间最小值的最大是多少~

                网上有一个类似的题目一样的题意,不过在那上面数据只有正数没有负数,所以,在满足某个数为最小的数的时候,直接调取之前所处理好的限定区间(在这个区间里认定的ai是最小的,可以通过单调栈O(n)获得).但这里不同,存在负数就存在着很多需要考虑的问题,之前的处理好的区间也不再是正确的了~。

                这里的话,我们先从双边进行遍历,分别获得ai左边的(包括这个点)的能够获取的最大的区间和,和最右边的(包括这个点)能够获取的最大的区间和。然后同样处理获得ai左边的(包括这个点)的能够获取的最小的区间和,和最右边的(包括这个点)能够获取的最小的区间和,那么我们就可以知道包含点ai的最大的区间和 和最小的区间和是多少了~~。这样的话,ai*(最大的区间和)和ai*(最小的区间和)其中一个肯定是以为ai最小点能够获得的最大的所求值。

                奥,补充一下,我们所获取的最大的区间和和最小的区间和可能超过了我们之前处理的限定区间,在这种情况下我们别忘了进行相减。

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
long long m[maxn];
long long sum[maxn], l[maxn], r[maxn];
long long zsum[maxn], zzsum[maxn];
long long fsum[maxn], ffsum[maxn];
int main() {
	ios::sync_with_stdio(0);
	int n;
	cin >> n;
	sum[0] = 0; 
	for (int i = 1; i <= n; i++) {
		cin >> m[i]; sum[i] = sum[i - 1] + m[i];
		l[i] = r[i] = i;
	}sum[n + 1] = sum[n];
	stack<int> s;
	int i = 1;
	while (i<=n) {
		if (s.empty() || m[i] > m[s.top()]) {
			s.push(i);
			++i;
		}
		else {
			l[i] = l[s.top()];
			s.pop();
		}
	}
	while (!s.empty())
		s.pop();
	i = n;
	while (i >= 1) {
		if (s.empty() || m[i] > m[s.top()]) {
			s.push(i);
			--i;
		}
		else {
			r[i] = r[s.top()];
			s.pop();
		}
	}


	long long su = 0, t = 0;
	for (int i = 1; i <= n; i++) {
		su += m[i];
		zsum[i] = su;
		if (t < l[i]) {
			zsum[i] -= sum[l[i] - 1] - sum[t];
		}
		if (su < 0) {
			su = 0;
			t = i;
		}
	}
	su = 0; t = n + 1;
	for (int i = n; i >= 1; i--) {
		su += m[i];
		zzsum[i] = su;
		if (t > r[i]) {
			zzsum[i] -= sum[t - 1] - sum[r[i]];
		}
		if (su < 0) {
			su = 0;
			t = i;
		}
	}
	// 负数开始。
	su = 0; t = 0;
	for (int i = 1; i <= n; i++) {
		su += m[i];
		fsum[i] = su;
	//	cout << su << " "<<t<<" "<<l[i]<<endl;
		if (t < l[i]) {
		//	cout << i <<" now: "<<sum[l[i]-1]<<" "<<sum[t]<< endl;
			fsum[i] -= sum[l[i] - 1] - sum[t];
		}
		if (su > 0) {
			su = 0;
			t = i;
		}
	}
	su = 0; t = n;
	for (int i = n; i >= 1; i--) {
		su += m[i];
		ffsum[i] = su;
		if (t > r[i]) {
			ffsum[i] -= sum[t - 1] - sum[r[i]];
		}
		if (su > 0) {
			su = 0;
			t = i;
		}
	}
	long long ans = -0x3f3f3f3f3f3f3f3f;
	for (int i = 1; i <= n; i++) {
		long long a = zsum[i] - m[i] + zzsum[i];
		long long b = fsum[i] - m[i] + ffsum[i];
		ans = max(m[i] * a, ans);
		ans = max(ans, m[i] * b);
	}
	cout << ans << "\n";
	return 0;
}

 

 

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
正在热议
更多
# 长得好看会提高面试通过率吗? #
3876次浏览 45人参与
# 离家近房租贵VS离家远但房租低,怎么选 #
16896次浏览 137人参与
# 巨人网络春招 #
11520次浏览 224人参与
# 春招至今,你的战绩如何? #
15630次浏览 144人参与
# 你的实习产出是真实的还是包装的? #
3051次浏览 53人参与
# 沪漂/北漂你觉得哪个更苦? #
1513次浏览 40人参与
# MiniMax求职进展汇总 #
25122次浏览 321人参与
# HR最不可信的一句话是__ #
1078次浏览 32人参与
# AI面会问哪些问题? #
935次浏览 23人参与
# 你做过最难的笔试是哪家公司 #
1228次浏览 22人参与
# AI时代,哪个岗位还有“活路” #
2814次浏览 51人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152901次浏览 889人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
8007次浏览 43人参与
# XX请雇我工作 #
51155次浏览 171人参与
# 简历第一个项目做什么 #
32131次浏览 360人参与
# 简历中的项目经历要怎么写? #
311028次浏览 4264人参与
# 投格力的你,拿到offer了吗? #
178337次浏览 891人参与
# 你最满意的offer薪资是哪家公司? #
76978次浏览 375人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
187585次浏览 1123人参与
# AI时代,哪些岗位最容易被淘汰 #
64704次浏览 883人参与
# 如果重来一次你还会读研吗 #
230010次浏览 2011人参与
# 正在春招的你,也参与了去年秋招吗? #
364336次浏览 2642人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务