[codeforces631E]Product Sum
1 second
256 megabytes
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.

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.
Print a single integer — the maximum possible value of characteristic of a that can be obtained by performing no more than one move.
4
4 3 2 5
39
5
1 1 2 7 1
49
3
1 1 2
9
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的更多相关文章
- 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 ...
- 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 ...
- Codeforces 631E Product Sum 斜率优化
我们先把问题分成两部分, 一部分是把元素往前移, 另一部分是把元素往后移.对于一个 i 后的一个位置, 我们考虑前面哪个移到这里来最优. 我们设最优值为val, val = max(a[ j ] ...
- CS Academy Sliding Product Sum(组合数)
题意 有一个长为 \(N\) 的序列 \(A = [1, 2, 3, \dots, N]\) ,求所有长度 \(\le K\) 的子串权值积的和,对于 \(M\) 取模. \(N \le 10^{18 ...
- @codeforces - 631E@ Product Sum
目录 @desription@ @solution@ @accepted code@ @details@ @desription@ 给定一个序列 a,定义它的权值 \(c = \sum_{i=1}^{ ...
- Subarray Product Less Than K LT713
Your are given an array of positive integers nums. Count and print the number of (contiguous) subarr ...
- 数据库sql语句规则
sql练习: 创建一个名称为mydb1的数据库. create database mydb1; 查看库 show databases; 创建一个使用utf-8字符集的mydb2数据库. create ...
- MySQL高级查询 之 与 Group By 一起使用的函数 和 关键字
1 GROUP_CONCAT mysql> SELECT student_name, -> GROUP_CONCAT(test_score) -> FROM stud ...
- HANA SQL
约束 注释 你可以给你的 SQL 语句添加注释来增加可读性和可维护性. SQL 语句中注释的分隔如下: l 双连字符“--”.所有在双连字符之后直到行尾的内容都被 SQL 解析器认为是注释. l ...
随机推荐
- jade模板引擎简明用法
①.特性 首个单词为标签,有一些不能识别的标签可作为code,如each for case if else if unless zen coding风格添加标签,如 .nb#hello 生成 & ...
- 计算进程消费cpu和内存
Linux下没有直接可以调用系统函数知道CPU占用和内存占用.那么如何知道CPU和内存信息呢.只有通过proc伪文件系统来实现. proc伪文件就不介绍了,只说其中4个文件.一个是/proc/stat ...
- H5 canvas圆形的时钟
今天用H5中的canvas标签做一个时钟,H5中有很多好用的新增标签,真的很不错. 1.canvas标签介绍 <canvas> 标签定义图形,比如图表和其他图像,你必须使用脚本来绘制图形. ...
- 使用Spire.Doc组件利用模板导出Word文档
以前一直是用Office的组件实现Word文档导出,但是让客户在服务器安装Office,涉及到版权:而且Office安装,包括权限配置也是比较麻烦. 现在流行使用第三方组件来实现对Office的操作, ...
- JDK的下载与配置
一.下载JDK 1.进入oracle官网 下载完成后直接运行就能生成jdk文件. 二.配置环境 1.打开环境配置 右击计算机选择属性 选择高级系统数据 点击环境变量 2.配置JAVA_HOME 新建一 ...
- java泛型探索——小特性
泛型特性(小篇幅) 1. 补充介绍一些常见的泛型特性: 类型参数T可以是recursive(类似递归性),它的边界可以是类型参数是自身的接口或类. 如我实现寻找最大值的方法,可以这么写: public ...
- hadoop集群中删除原有jdk设置
普通用户: sudo rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-1.50.1.11.5.el6_3.x86_64 tzdata-java-2012j-1.e ...
- CentOS6.5_x86安装Mysql5.5.49
1.说明: 安装MySQL主要有两种方法:一种是通过源码自行编译安装,这种适合高级用户定制MySQL的特性,这里不做说明:另一种是通过编译过的二进制文件进行安装.二进制文件安装的方法又分为两种:一种是 ...
- eclipse C 开发 Stm32
版权声明:本文为博主原创文章,未经博主允许不得转载. 1.下载eclipse需要的运行环境,JDK/JRE. 在http://wiki.eclipse.org/Eclipse/Installation ...
- PHP导出生成excel文件
composer包管理工具还是非常好用的 下载安装的扩展比较靠谱 无需自己解决扩展BUG 省时省力提高效率 1.下载安装composer自行百度 2.通过composer下载安装office 3.不在 ...