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 <= n <= 5*10^5).
Second line contains n integers represent the array a (-10^5 <= ai <= 10^5).
Output
One line contains an integer represent the answer of the array.
题意:
((区间和)乘(区间最小值))的最大值
题目链接:https://nanti.jisuanke.com/t/38228
思路:
这个题和POJ2796差不多,就是范围不同。http://poj.org/problem?id=2796
此题可以先用单调栈判断以每个值为最小值的最大左边界和右边界。后面,对每个值分成负数和正数讨论,
①如果为正数,取区间和最大值。
②如果为负数,取区间和最小值。
可以用线段树来维护前缀和。然后查找区间最值。
如果为正数,那么直接右端点前缀和-左端点前缀和
如果为负数,这时你要找区间和最小值,那么你可以右端找一个最小值-左端找一个最大值,那么这时就是最小值(如果左端最大值为负值,这时负数-负数会变大,所以不能减)。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 500000+50;
const long long INF = 0x3f3f3f3f;
typedef long long ll;
ll a[maxn], pre[maxn];
ll minn[maxn<<2], maxx[maxn<<2];
int Left[maxn], Right[maxn];
void buildTree(int l, int r, int rt)
{
if(l == r) {
maxx[rt] = minn[rt] = pre[l];
return;
}
int mid = (l+r)>>1;
buildTree(l,mid,rt<<1);
buildTree(mid+1,r,rt<<1|1);
maxx[rt] = max(maxx[rt<<1], maxx[rt<<1|1]);
minn[rt] = min(minn[rt<<1], minn[rt<<1|1]);
}
int qmax(int l, int r, int rt, int L, int R)
{
if(L <= l && r <= R)
{
return maxx[rt];
}
int mid = (l + r) >> 1;
int ans = -INF;
if(L <= mid)
ans = max(ans, qmax(l, mid, rt<<1, L, R));
if(R > mid)
ans = max(ans, qmax(mid+1, r, rt<<1|1, L, R));
return ans;
}
int qmin(int l, int r, int rt, int L, int R)
{
if(L <= l && r <= R)
{
return minn[rt];
}
int mid = (l + r) >> 1;
int ans = INF;
if(L <= mid)
ans = min(ans, qmin(l, mid, rt<<1, L, R));
if(R > mid)
ans = min(ans, qmin(mid+1, r, rt<<1|1, L, R));
return ans;
}
int main()
{
int t;
scanf("%d", &t);
int x;
for(int i = 1; i <= t; i++) {
scanf("%lld", &a[i]);
pre[i] = pre[i-1] + a[i];
}
buildTree(1, t, 1);
stack<int > s;
while(s.size()){
s.pop();
}
for(int i = 1; i <= t; i++) {
while(s.size() && a[s.top()]>a[i]) {
Right[s.top()] = i-1;
s.pop();
}
s.push(i);
}
while(s.size()) {
Right[s.top()] = t;
s.pop();
}
for(int i = t; i >= 1; i--) {
while(s.size() && a[s.top()] > a[i]) {
Left[s.top()] = i+1;
s.pop();
}
s.push(i);
}
while(s.size()) {
Left[s.top()] = 1;
s.pop();
}
ll res = -1e18;
for(int i = 1; i <= t; i++) {
if(a[i] > 0) {
res = max(res, a[i] * (pre[Right[i]] - pre[Left[i] - 1]));
}
else {
res = max(res, a[i] * (qmin(1,t,1,i,Right[i]) - max(0,qmax(1, t, 1, Left[i], i))));
}
}
printf("%lld\n", res);
return 0;
}