Codeforces Round #344 (Div. 2) E. Product Sum 维护凸壳

E. Product Sum

题目连接:

http://www.codeforces.com/contest/631/problem/E

Description

Blake is the boss of Kris, however, this doesn’t spoil their friendship. They often gather at the bar to talk about intriguing problems about maximising some values. This time the problem is really special.

You are given an array a of length n. The characteristic of this array is the value — the sum of the products of the values ai by i. One may perform the following operation exactly once: pick some element of the array and move to any position. In particular, it’s allowed to move the element to the beginning or to the end of the array. Also, it’s allowed to put it back to the initial position. The goal is to get the array with the maximum possible value of characteristic.

Input

The first line of the input contains a single integer n (2 ≤ n ≤ 200 000) — the size of the array a.

The second line contains n integers ai (1 ≤ i ≤ n, |ai| ≤ 1 000 000) — the elements of the array a.

Output

Print a single integer — the maximum possible value of characteristic of a that can be obtained by performing no more than one move.

Sample Input

4
4 3 2 5

Sample Output

39

Hint

题意

给你n个数,每个数是a[i]

然后所有数的答案就是sigma(i*a[i])

现在你可以随便交换两个数的位置

问你最后最大的答案是多少

题解:

考虑这个数和后面的数交换,那么增加的值是a[l]*(r-l)-(a[l+1]+…+a[r])

和前面的交换的话,a[r]*(l-r)+(a[l]+…+a[r-1])

然后我们分开考虑,先考虑和前面交换的

可以化简为(a[r]*l-sum[l-1])+(sum[r-1]-a[r]*r),显然我们直接暴力枚举r,然后找到一个最大的(a[r]*l-sum[l-1])就好了

这个东西可以抽象成在平面上的很多直线,斜率为l,截距为-sum[l-1]。

每一个决策可以看成平面上的点,当然我们只会选凸包上的点咯,然后不断维护这个凸包就好了。

考虑和后面交换同理。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
int n;
long long sum[maxn];
long long ans,dans;
long long a[maxn];
struct Convex_Hull
{
    int sz;
    pair<long long,long long> line[maxn];
    void init()
    {
        memset(line,0,sizeof(line));
        sz=0;
    }
    long long get(int p,long long x)
    {
        return line[p].first*x+line[p].second;
    }
    bool is_bad(long long x,long long y,long long z)
    {
        long long fi = (line[x].second-line[z].second)*(line[x].first-line[y].first);
        long long se = (line[y].second-line[x].second)*(line[z].first-line[x].first);
        return fi<=se;
    }
    void add(long long x,long long y)
    {
        line[sz++]=make_pair(x,y);
        while(sz>2&&is_bad(sz-2,sz-3,sz-1))
            line[sz-2]=line[sz-1],sz--;
    }
    long long query(long long x)
    {
        int l = -1 ,r = sz-1;
        while(r-l>1)
        {
            int mid = (l+r)/2;
            if(get(mid,x)<=get(mid+1,x))l=mid;
            else r=mid;
        }
        return get(r,x);
    }
}H;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        sum[i]=sum[i-1]+a[i];
        ans=ans+a[i]*i;
    }
    H.init();
    for(int i=2;i<=n;i++)
    {
        H.add(i-1,-sum[i-2]);
        dans=max(dans,H.query(a[i])+sum[i-1]-a[i]*i);
    }
    H.init();
    for(int i=n-1;i>=1;i--)
    {
        H.add(-(i+1),-sum[i+1]);
        dans=max(dans,H.query(-a[i])+sum[i]-a[i]*i);
    }
    cout<<ans+dans<<endl;
}
    原文作者:qscqesze
    原文地址: https://www.cnblogs.com/qscqesze/p/5243768.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞