E. Product Sum
time limit per test:

1 second

memory limit per test:

256 megabytes

input:standard input
output:standard output

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 valuesai 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.

Examples
input
4
4 3 2 5
output
39
input
5
1 1 2 7 1
output
49
input
3
1 1 2
output
9
Note

In the first sample, one may pick the first element and place it before the third (before 5). Thus, the answer will be3·1 + 2·2 + 4·3 + 5·4 = 39.

In the second sample, one may pick the fifth element of the array and place it before the third. The answer will be1·1 + 1·2 + 1·3 + 2·4 + 7·5 = 49.

题解:

刚看这个题我十分的懵逼,这怎么做?

于是我就想了个暴力O(n2)的算法:如果没有这个"exactly once"的移动,问题的答案很容易算出来,设为ans

而由于只能移动一次,所以我可以枚举移动的方案,看每种移动对答案的贡献,设为delta,选最大贡献,最终答案为ans+delta

scanf("%d",&n);
for(LL i=;i<=n;i++)
{
cin>>a[i];
s[i]=a[i]+s[i-];
ans1+=a[i]*i;
}
for(int l=;l<=n;l++)
for(int r=l+;r<=n;r++)
{
delta=max(delta,a[l]*(r-l)-(s[r]-s[l]));
delta=max(delta,s[r-]-s[l-]-a[r]*(r-l));
}
cout<<delta+ans1;

一个简单的暴力

这样肯定会t,所以我们考虑一下刚才那个暴力的式子

"delta=max(delta,a[l]*(r-l)-(s[r]-s[l]));"

"delta=max(delta,s[r-1]-s[l-1]-a[r]*(r-l));"

把这两个式子变形,可以得到:

a[l]*(r-l)-(s[r]-s[l])=a[l]*r-a[l]*l-s[r]+s[l]=(a[l]*r-s[r])+(s[l]-a[l]*l)

s[r-1]-s[l-1]-a[r]*(r-l)=a[r]*l-a[r]*r+s[r-1]-s[l-1]=(a[r]*l-s[l-1])+(s[r-1]-a[r]*r)

对于每一个l/r,右面括号里的项都是确定的,现在需要的就是确定左面括号中的最大值

而左面括号的式子形如一个k*x+b的一次函数,所以不难想到维护一个下凸壳,对于每个a[i]在下凸壳中查找

不过,这个式子并没有决策单调性,所以我们不能用单调队列维护,而是一直保存着那个下凸壳,每次用log(n)二分查找

这样就可以解决这个问题了,最后答案依然是ans+delta

代码见下:

 #include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long LL;
const int N=;
int n;
inline LL max(LL a,LL b){return a>b?a:b;}
LL a[N],s[N],ans1,delta=;
struct node{LL a,b;};
inline LL f(LL a,node b){return b.a*a+b.b;}
node q[N];int h,t;
inline LL query(LL x)
{
int le=,ri=t;
while(ri-le>)
{
int mi=(le+ri)>>;
if(f(x,q[mi])<=f(x,q[mi+]))
le=mi;
else ri=mi;
}
return f(x,q[ri]);
}
int main()
{
scanf("%d",&n);
for(LL i=;i<=n;i++)
{
cin>>a[i];
s[i]=a[i]+s[i-];
ans1+=a[i]*i;
}
t=;
for(LL r=;r<=n;r++)
{
node tmp=(node){r-,-s[r-]};
while(t>&&(q[t].b-tmp.b)*(q[t].a-q[t-].a)<=(q[t-].b-q[t].b)*(tmp.a-q[t].a))t--;
q[++t]=tmp;
delta=max(delta,query(a[r])-a[r]*r+s[r-]);
}
t=;
for(LL l=n-;l>=;l--)
{
node tmp=(node){-(l+),-s[l+]};
while(t>&&(q[t].b-tmp.b)*(q[t].a-q[t-].a)<=(q[t-].b-q[t].b)*(tmp.a-q[t].a))t--;
q[++t]=tmp;
delta=max(delta,query(-a[l])-a[l]*l+s[l]);
}
cout<<delta+ans1;
}

codeforces631E

[codeforces631E]Product Sum的更多相关文章

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

    E. Product Sum 题目连接: http://www.codeforces.com/contest/631/problem/E Description Blake is the boss o ...

  2. Codeforces Round #344 (Div. 2) E. Product Sum 二分斜率优化DP

    E. Product Sum   Blake is the boss of Kris, however, this doesn't spoil their friendship. They often ...

  3. Codeforces 631E Product Sum 斜率优化

    我们先把问题分成两部分, 一部分是把元素往前移, 另一部分是把元素往后移.对于一个 i 后的一个位置, 我们考虑前面哪个移到这里来最优. 我们设最优值为val,   val = max(a[ j ] ...

  4. CS Academy Sliding Product Sum(组合数)

    题意 有一个长为 \(N\) 的序列 \(A = [1, 2, 3, \dots, N]\) ,求所有长度 \(\le K\) 的子串权值积的和,对于 \(M\) 取模. \(N \le 10^{18 ...

  5. @codeforces - 631E@ Product Sum

    目录 @desription@ @solution@ @accepted code@ @details@ @desription@ 给定一个序列 a,定义它的权值 \(c = \sum_{i=1}^{ ...

  6. Subarray Product Less Than K LT713

    Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...

  7. 数据库sql语句规则

    sql练习: 创建一个名称为mydb1的数据库. create database mydb1; 查看库 show databases; 创建一个使用utf-8字符集的mydb2数据库. create ...

  8. MySQL高级查询 之 与 Group By 一起使用的函数 和 关键字

    1 GROUP_CONCAT mysql> SELECT student_name, ->     GROUP_CONCAT(test_score) ->     FROM stud ...

  9. HANA SQL

    约束 注释 你可以给你的 SQL 语句添加注释来增加可读性和可维护性. SQL 语句中注释的分隔如下: l  双连字符“--”.所有在双连字符之后直到行尾的内容都被 SQL 解析器认为是注释. l  ...

随机推荐

  1. 2017/4/27-Gradle的配置与Spring的下载

    Gradle的配置与Spring的下载 1.Gradle 1) 介绍 Gradle是一个基于Groovy的构建工具,类似Maven,但是比其更加简单轻便.它可以自动化地进行软件构建.测试.发布.部署. ...

  2. MATLAB下跑Faster-RCNN+ZF实验时如何编译自己需要的external文件

    本篇文章主讲这篇博客中的(http://blog.csdn.net/sinat_30071459/article/details/50546891)的这个部分,如图所示 注:截图来自 小咸鱼_ 的博客 ...

  3. Windows7系统的封装

    系统装到虚拟机优化完成以后,可以装上自己想要装的软件,也可以不装做个纯净版的.今天用ES封装,首先打开一般我们只点这四项就够了,如下图 写上自己想写的,也可以不写系统默认,直接点“下一步”关闭设备管理 ...

  4. ASP.NET Core实现强类型Configuration读取配置数据

    前言 实现读取JSON文件几种方式,在项目中采取老办法简单粗暴,结果老大过来一看,恩,这样不太可取,行吧那我就用.NET Core中最新的方式诺,切记,适合的才是最好的,切勿懒. .NET Core读 ...

  5. unity collider 和 trigger 触发条件

    物体A,物体B(都含有collider组件) collider触发条件:A和B至少一方是  未勾选is Kinematic的rigidbody,且都未勾选 is trigger.当只有一方是rigid ...

  6. 直方图均衡化CImg实现

    这篇博客是关于试用CImg库来实现灰度图和彩色图的直方图均衡化操作.感觉效果还不错,除了彩色图在均衡化时会有一定的色彩失真. C++代码实现: // // hEqualization.hpp // 直 ...

  7. MongoDB Java Driver 3.4操作

    导入jar包 <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-dr ...

  8. 用php(session)实现留言板功能----2017-05-09

    要实现留言功能,发送者和接受者必不可少,其次就是留言时间留言内容. 要实现的功能: 1.登录者只能查看自己和所有人的信息,并能够给好友留言 2.留言板页面,好友采取下拉列表,当留言信息为空时,显示提示 ...

  9. Ehcache 的简单实用 及配置

    Ehcache 与 spring 整合后的用法,下面是一个Ehcache.xml配置文件: 通用的缓存策略 可以用一个 cache: <?xml version="1.0" ...

  10. poj3067 Japan 树状数组求逆序对

    题目链接:http://poj.org/problem?id=3067 题目就是让我们求连线后交点的个数 很容易想到将左端点从小到大排序,如果左端点相同则右端点从小到大排序 那么答案即为逆序对的个数 ...