codeforces 631E Product Sum (dp凸单调性)

15 篇文章 1 订阅
<a target=_blank href="http://codeforces.com/problemset/problem/631/E" style="color: rgb(0, 0, 204); margin-top: 0px; font-family: verdana, arial, sans-serif; font-size: 13px; text-align: center;">Product Sum</a>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<stdio.h>
#include<algorithm>
#include<cmath>
#include<map>
#include<queue>
#include<bitset>
#include<stack>
using namespace std;


#pragma comment(linker, "/STACK:1024000000,1024000000")
#define inf 0x3f3f3f3f
#define eps 1e-9
#define pii pair<int,int>
#define MP make_pair
#define LL  long long
#define ULL unsigned long long 
#define N ( 1000000 + 10 )
#define M ( 200000 + 10)
#define mod  1000000007
/*
i < j
$ans[i][j] = {(i, j-1) | a[i] * (i+1)} + a[j] * i - ( {(i,j-1) | a[i] * i} + a[j] * j);
            = a[j] * (i-j) + sum[i][j-1]
            = a[j] * i - a[j]*j + s[j-1] - s[i-1];
            = a[j] * i - s[i-1] + s[j-1] - a[j]*j; // f[j] = s[j-1] - a[j] * j
            = a[j] * i - s[i-1] + f[j]; // g[i]
            i1 < i2
            a[j] * i1 - s[i1-1] < a[j] * i2 - s[i2-1]
            (s[i2-1] - s[i1-1])/(i2-i1) > a[j] // ll(i1, i2)
            i1 < i2 < i
			ll(i1, i2) >= ll(i2, i)
			(s[i2-1] - s[i1-1])/(i2-i1) >= (s[i-1] - s[i2-1]) / (i-i2)
            --

#ans[i][j] = {(i+1, j) | a[i] * (i-1)} + a[i] * j - ( {(i+1,j) | a[i] * i} + a[i] * i);
            = a[i] * (j-i) - sum[i+1][j]
            = a[i] * j - a[i] * i - (s[j] - s[i])
            = a[i] * j - s[j] + (-a[i] * i + s[i])  //-f[i] = a[i] * i - s[i]
            = a[i] * j - s[j] - f[i]; // g[j]
            j1 < j2
            g[j1] > g[j2]
            a[i] * j1 - s[j1] - f[i] > a[i] * j2 - s[j2] - f[i]
            a[i] * j1 - s[j1] > a[i] * j2 - s[j2]
            a[i] * (j1-j2) > s[j1] - s[j2]
            (s[j1] - s[j2])/(j1-j2) < a[i] //ll(j2, j1)
			j < j1 < j2
			ll(j1, j) >= (j2, j1) 
			(s[j] - s[j1])/(j-j) >= (s[j1] - s[j2])/(j1-j2)

			  >    >
ans = max(max(#ans[i]) + init)
*/

int a[N];
LL sum[N];
int tot;
struct point{
    LL a, s;
    LL get(int i) {
        return a * i - s;
    }
};
point que[N];
bool judge(point i1, point i2, point i) {
    return (i.s - i2.s) * (i2.a - i1.a) <= (i2.s - i1.s) * (i.a - i2.a);
}
void insert(LL a, LL s) {
    point tmp;
    tmp.a = a, tmp.s = s;
    while(tot >= 2 && judge(que[tot-2], que[tot-1], tmp))
        --tot;
    que[tot++] = tmp;
}

LL query(int x) {
    int l = -1, r = tot-1;
    while(r-l>1) {
        int mid = l+r>>1;
        if(que[mid].get(x) <= que[mid+1].get(x))
            l = mid;
        else r = mid;
    }
    return que[r].get(x);
}

int main() {
    int n;
    scanf("%d", &n);
    LL ans = 0, init= 0;
    sum[0] = 0;
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        init += (LL)a[i] * i;
        sum[i] = sum[i-1] + a[i];
    }
    tot = 0;
    for(int i = 2; i <= n; ++i) {
        insert(i-1, sum[i-2]);
        ans = max(ans, query(a[i]) + sum[i-1] - (LL)a[i] * i);
    }
    tot = 0;
    for(int i = n-1; i >= 1; --i) {
        insert(-(i+1), sum[i+1]);
        ans = max(ans, query(-a[i]) - (LL)a[i] * i + sum[i]);
    }
    printf("%I64d\n", ans + init);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值