3675: [Apio2014]序列分割

Time Limit: 40 Sec  Memory Limit: 128 MB

Submit: 3366  Solved: 1355

[Submit][Status][Discuss]

Description

小H最近迷上了一个分隔序列的游戏。在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列。为了得到k+1个子序列,小H需要重复k次以下的步骤:
1.小H首先选择一个长度超过1的序列(一开始小H只有一个长度为n的序列——也就是一开始得到的整个序列);
2.选择一个位置,并通过这个位置将这个序列分割成连续的两个非空的新序列。
每次进行上述步骤之后,小H将会得到一定的分数。这个分数为两个新序列中元素和的乘积。小H希望选择一种最佳的分割方式,使得k轮之后,小H的总得分最大。

Input

输入第一行包含两个整数n,k(k+1≤n)。

第二行包含n个非负整数a1,a2,...,an(0≤ai≤10^4),表示一开始小H得到的序列。

Output

输出第一行包含一个整数,为小H可以得到的最大分数。

Sample Input

7 3


4 1 3 4 0 2 3

Sample Output

108

HINT

【样例说明】 



在样例中,小H可以通过如下3轮操作得到108分: 



1.-开始小H有一个序列(4,1,3,4,0,2,3)。小H选择在第1个数之后的位置 



将序列分成两部分,并得到4×(1+3+4+0+2+3)=52分。 



2.这一轮开始时小H有两个序列:(4),(1,3,4,0,2,3)。小H选择在第3个数 



字之后的位置将第二个序列分成两部分,并得到(1+3)×(4+0+2+ 



3)=36分。 



3.这一轮开始时小H有三个序列:(4),(1,3),(4,0,2,3)。小H选择在第5个 



数字之后的位置将第三个序列分成两部分,并得到(4+0)×(2+3)= 



20分。 



经过上述三轮操作,小H将会得到四个子序列:(4),(1,3),(4,0),(2,3)并总共得到52+36+20=108分。 



【数据规模与评分】 



:数据满足2≤n≤100000,1≤k≤min(n -1,200)。

经观察发现,当分割点确定后,分割的顺序对结果没有影响。

就比如a,b,c割两次

bc + a(b + c) = ab + ac + bc

ab + c(a + b) = ab + ac + bc

所以我们可以设f[k][i]表示第k次割第i个位置的最大价值

有f[k][i] = max{f[k - 1][j] + (s[j + 1] - s[i + 1]) * s[i + 1]};【s[i]为后缀和】

划为斜截式就是 -s[i + 1] * s[j + 1] + f[k][i] = f[k - 1][j]

使截距最大,维护凸包

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define eps 1e-9
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define fo(i,x,y) for (int i = (x); i <= (y); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 100005,maxm = 105,INF = 1000000000;
inline int read(){
int out = 0,flag = 1;char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = out * 10 + c - 48; c = getchar();}
return out * flag;
}
LL n = 0,N,K,A[maxn],B[maxn],s[maxn],f[2][maxn],q[maxn],head,tail,p = 1,now = 0;
inline double slope(int u,int v){
return (double)(f[p][u] - f[p][v]) / (s[u + 1] - s[v + 1]);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out1.txt","w",stdout);
N = read(); K = read();
REP(i,N) A[i] = read();
REP(i,N) if (A[i]) B[++n] = A[i];
for (int i = n; i > 0; i--) s[i] = s[i + 1] + B[i];
for (int k = 1; k <= K; k++,p ^= 1,now ^= 1){
q[head = tail = 0] = 0;
for (int i = 1; i <= n; i++){
while (head < tail && slope(q[head],q[head + 1]) < -s[i + 1] + eps) head++;
int j = q[head];
//cout<<j<<' ';
f[now][i] = f[p][j] + (s[j + 1] - s[i + 1]) * s[i + 1];
while (head < tail && slope(q[tail],q[tail - 1]) > slope(i,q[tail]) + eps) tail--;
q[++tail] = i;
}
//REP(i,n) cout<<f[now][i]<<' ';cout<<endl;
}
LL ans = 0;
REP(i,n) ans = max(ans,f[p][i]);
cout<<ans<<endl;
return 0;
}

BZOJ3675 [Apio2014]序列分割 【斜率优化dp】的更多相关文章

  1. bzoj3675[Apio2014]序列分割 斜率优化dp

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3508  Solved: 1402[Submit][Stat ...

  2. 【bzoj3675】[Apio2014]序列分割 斜率优化dp

    原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...

  3. [APIO2014]序列分割 --- 斜率优化DP

    [APIO2014]序列分割 题目大意: 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的操作\(k ...

  4. BZOJ3675: [Apio2014]序列分割(斜率优化)

    Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 4186  Solved: 1629[Submit][Status][Discuss] Descript ...

  5. BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)

    洛谷传送门 题目大意:让你把序列切割k次,每次切割你能获得 这一整块两侧数字和的乘积 的分数,求最大的分数并输出切割方案 神题= = 搞了半天也没有想到切割顺序竟然和答案无关...我太弱了 证明很简单 ...

  6. BZOJ 3675 APIO2014 序列切割 斜率优化DP

    题意:链接 方法:斜率优化DP 解析:这题BZ的数据我也是跪了,特意去网上找到当年的数据后面二十个最大的点都过了.就是过不了BZ. 看到这道题自己第一发DP是这么推得: 设f[i][j]是第j次分第i ...

  7. P3648 [APIO2014]序列分割 斜率优化

    题解:斜率优化\(DP\) 提交:\(2\)次(特意没开\(long\ long\),然后就死了) 题解: 好的先把自己的式子推了出来: 朴素: 定义\(f[i][j]\)表示前\(i\)个数进行\( ...

  8. 【BZOJ3675】【APIO2014】序列分割 [斜率优化DP]

    序列分割 Time Limit: 40 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 小H最近迷上了一个分隔序列的游戏. ...

  9. BZOJ 3675: 序列分割 (斜率优化dp)

    Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...

  10. 2018.09.29 bzoj3675: [Apio2014]序列分割(斜率优化dp)

    传送门 斜率优化dp经典题目. 首先需要证明只要选择的K个断点是相同的,那么得到的答案也是相同的. 根据分治的思想,我们只需要证明有两个断点时成立,就能推出K个断点时成立. 我们设两个断点分成的三段连 ...

随机推荐

  1. 抓取Oracle数据快照

    进入到oracle安装目录下的admin(找到这个目录)开启cmd键入sqlplus system/mima@实例名>@awrrpt.sql Would you like an HTML rep ...

  2. 「日常训练」Girls and Boys(HDU-1068)

    题意 有n个同学,给出同学之间的爱慕关系,选出一个集合使得集合中的人没有爱慕关系.问能选出的最大集合是多少. 分析 二分图的最大独立集. 最大独立集的意思是,在图中选出最多的点,使他们两两之间没有边, ...

  3. idea前端页面不刷新----springboot

    修改这里就好了

  4. Unity Lighting - The Precompute Process 预计算过程(二)

      The Precompute Process 预计算过程 In Unity, precomputed lighting is calculated in the background - eith ...

  5. 编写你自己的Python模块

    其实网上Python教程挺多的,编写你自己的模块很简单,这其实就是你一直在做的事情!这是因为每一个 Python 程序同时也是一个模块.你只需要保证它以 .py 为扩展名即可.下面的案例会作出清晰的解 ...

  6. 【setUp-tearDown】线程组开始,结束各执行一次

    使用setUp线程组的方式  ——> 开始 使用tearDown线程组 的方式 ——>结束

  7. vue移动音乐app开发学习(一):环境搭建

    本系列文章是为了记录学习中的知识点,便于后期自己观看.如果有需要的同学请登录慕课网,找到Vue 2.0 高级实战-开发移动端音乐WebApp进行观看,传送门. 一:使用vue-cli脚手架搭建: 1: ...

  8. 最短路径——floyd(多源最短路径)

    #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> ...

  9. 第三课——MFC编程

    一.MFC概述 1. MFC简述 MFC不仅仅是一套基础类库,更是一种编程方式. 2. MFC由来 1987年微软公司推出了第一代Windows产品,并为应用程序设计者提供了Win16(16位Wind ...

  10. Mishka and Contest(模拟水题)

    Mishka started participating in a programming contest. There are nn problems in the contest. Mishka' ...