@codeforces - 631E@ Product Sum
@desription@
给定一个序列 a,定义它的权值 \(c = \sum_{i=1}^{n}a_i\)。
你可以做如下的操作恰好一次:选择一个数,然后将它移动到一个位置(可以是原位置,序列开头与结尾)。
最大化序列权值。
input
第 1 行一个整数 n,表示序列长度(2 <= n <= 200000)。
第 2行 n 个整数 a1, a2, ..., an,表示这个序列(|ai| <= 1000000)。
output
输出一个整数,表示最大的序列权值。
sample input
4
4 3 2 5
sample output
39
sample explain
将 4 移动到 5 之前,得到 \(c = 1*3 + 2*2 + 3*4 + 4*5 = 39\)。

@solution@
移动可以向前移动也可以向后移动,我们仅考虑向后这一种,向前同理。
记原序列权值为 \(c\),再记 \(s[i]=\sum_{p=1}^{i}a_p\)。
考虑将第 i 号元素移动到第 j 个位置,则新序列权值为:
\]
你看,它多么的斜率优化。
求最大值是上凸包,横坐标为 \(-j\),从后往前是单增的。
但是……斜率为 \(a[i]\),是不单调的。
所以我们必须在凸包上作二分寻找答案。
一开始我很懵逼,凸包不应该是三分求极值吗?后来我才发现,二分原来是二分斜率。凸包上斜率是单增的,所以可以使用二分。(但是三分好像也可以……只是大概没人想写而已……明明三分更容易调错来着 qwq)。
二分找什么呢?就是找到一个点,它和它前驱的斜率大于等于 \(a[i]\),它和它后继的斜率小于等于 \(a[i]\)。
注意二分常见的错误:边界。
@accepted code@
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 200000;
int n;
ll a[MAXN + 5], s1[MAXN + 5], s2[MAXN + 5];
ll c1(int i) {return s1[n] - a[i]*i + s2[i-1];}
ll c2(int i) {return s1[n] - a[i]*i + s2[i];}
ll k1(int i) {return -a[i];}
ll k2(int i) {return a[i];}
ll x1(int j) {return j;}
ll x2(int j) {return -j;}
ll y1(int j) {return -s2[j-1];}
ll y2(int j) {return -s2[j];}
int stk[MAXN + 5], tp;
double slope1(int p, int q) {return 1.0*(y1(p) - y1(q))/(x1(p) - x1(q));}
double slope2(int p, int q) {return 1.0*(y2(p) - y2(q))/(x2(p) - x2(q));}
int main() {
scanf("%d", &n);
for(int i=1;i<=n;i++)
scanf("%lld", &a[i]);
for(int i=1;i<=n;i++) {
s1[i] = s1[i-1] + a[i]*i;
s2[i] = s2[i-1] + a[i];
}
ll ans = -(1LL<<62); tp = 0;
for(int i=1;i<=n;i++) {
while( tp > 1 && slope1(stk[tp - 1], stk[tp]) <= slope1(stk[tp], i) )
tp--;
stk[++tp] = i;
int le = 1, ri = tp;
while( le < ri ) {
int mid = (le + ri) >> 1;
if( slope1(stk[mid], stk[mid+1]) <= k1(i) ) ri = mid;
else le = mid + 1;
}
ans = max(ans, c1(i) + y1(stk[le]) - k1(i)*x1(stk[le]));
}
tp = 0;
for(int i=n;i>=1;i--) {
while( tp > 1 && slope2(stk[tp - 1], stk[tp]) <= slope2(stk[tp], i) )
tp--;
stk[++tp] = i;
int le = 1, ri = tp;
while( le < ri ) {
int mid = (le + ri) >> 1;
if( slope2(stk[mid], stk[mid+1]) <= k2(i) ) ri = mid;
else le = mid + 1;
}
ans = max(ans, c2(i) + y2(stk[le]) - k2(i)*x2(stk[le]));
}
printf("%lld\n", ans);
}
@details@
一开始我从前往后和从后往前都用同一个横坐标,然后因为枚举顺序不一样,导致一个是单增的一个是单减的。
单增的还好,单减的那个让我二分时各种边界错误……调到死都调不出来……
最后索性把单减那个横坐标取个相反数,变成单增的。然后一遍过 =_=。
@codeforces - 631E@ Product Sum的更多相关文章
- Codeforces 631E Product Sum 斜率优化
我们先把问题分成两部分, 一部分是把元素往前移, 另一部分是把元素往后移.对于一个 i 后的一个位置, 我们考虑前面哪个移到这里来最优. 我们设最优值为val, val = max(a[ j ] ...
- 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 396B On Sum of Fractions 数论
题目链接:Codeforces 396B On Sum of Fractions 题解来自:http://blog.csdn.net/keshuai19940722/article/details/2 ...
- [codeforces631E]Product Sum
E. Product Sum time limit per test: 1 second memory limit per test: 256 megabytes input:standard inp ...
- codeforces 963A Alternating Sum
codeforces 963A Alternating Sum 题解 计算前 \(k\) 项的和,每 \(k\) 项的和是一个长度为 \((n+1)/k\) ,公比为 \((a^{-1}b)^k\) ...
- codeforces 1217E E. Sum Queries? (线段树
codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...
- Codeforces 577B Modulo Sum
http://codeforces.com/problemset/problem/577/B 题意:有n个数,求有无一个子序列满足和是m的倍数 思路:用模下的背包做,发现n是十的六次方级别,但是有个神 ...
- Codeforces 85 D. Sum of Medians
题目链接:http://codeforces.com/contest/85/problem/D 做法果然男默女泪啊..... 大概就是直接开了一个$vector$每次插入删除都用自带的$insert$ ...
随机推荐
- GIT → 10:基于IntelliJ IDEA的Git 操作
GIT → 10:基于IntelliJ IDEA的Git 操作
- windows 环境下搭建docker私有仓库
windows 环境下搭建docker私有仓库 1.在公用仓库中pull仓库镜像 docker pull regitry 2.启动仓库镜像 //-d意思是后台运行,-p是做端口映射,这里是将本地的50 ...
- VUE.之安装 font-awesome
VUE.之安装 font-awesome 我们在项目中经常使用各种图标:font-awesome (http://fontawesome.dashgame.com/) 1.npm 安装font-awe ...
- 洛谷P1969 [NOIP2013提高组Day2T1] 积木大赛
P1969 积木大赛 题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前, ...
- 【P2616】 【USACO10JAN】购买饲料II Buying Feed, II
P2616 [USACO10JAN]购买饲料II Buying Feed, II 题目描述 Farmer John needs to travel to town to pick up K (1 &l ...
- Jquery选择器分类:基本选择器,层次选择器,过滤选择器,表单选择器。
基本选择器 说明:通过元素id.class和标签名等来查找DOM元素 1.id选择器:$("#test");//选取id为test的元素 2.类选择器:$(".test& ...
- golang之for
1.常规for.结构如下: for 初始化语句; 条件语句; 修饰语句{ 循环体 } 2.条件for.结构如下: 初始化语句; for 条件语句 { 循环体 } 3.死循环 for.结构如下: for ...
- Faster RCNN算法训练代码解析(1)
这周看完faster-rcnn后,应该对其源码进行一个解析,以便后面的使用. 那首先直接先主函数出发py-faster-rcnn/tools/train_faster_rcnn_alt_opt.py ...
- web服务发展历程
PhP发展历史1.php: 开始名字含义:personal home page 个人网页 现在名字含义:HyperText Perprocessor 超文本预处理语言 预处理: 说明PHP是在服务器预 ...
- 写论文,没数据?R语言抓取网页大数据
写论文,没数据?R语言抓取网页大数据 纵观国内外,大数据的市场发展迅猛,政府的扶持也达到了空前的力度,甚至将大数据纳入发展战略.如此形势为社会各界提供了很多机遇和挑战,而我们作为卫生(医学)统计领域的 ...