zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    谷歌是如何以简洁赢取用户的
    不是乔布斯的命,别得乔布斯的病
    Android菜单详解(五)——使用XML生成菜单
    Android Matrix理论与应用详解(转载)
    android Bitmap用法总结
    android每次调试程序 模拟器都重新启动的解决办法
    Android图片处理(Matrix,ColorMatrix)(转载)
    Androdi SoftReference(Android 软引用)
    java synchronized详解
    Android的Activity屏幕切换动画(一)左右滑动切换
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5243768.html
Copyright © 2011-2022 走看看