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. ElasticSearch搜索引擎安装配置中文分词器IK插件

    近几篇ElasticSearch系列: 1.阿里云服务器Linux系统安装配置ElasticSearch搜索引擎 2.Linux系统中ElasticSearch搜索引擎安装配置Head插件 3.Ela ...

  2. vim python自动补全插件:pydiction

    vim python自动补全插件:pydiction 可以实现下面python代码的自动补全: 1.简单python关键词补全 2.python 函数补全带括号 3.python 模块补全 4.pyt ...

  3. python同时遍历两个list

    两个list, 有对应关系,希望同时完成遍历 用迭代器迭代的方法也不是不可以,python提供了更直观的方法: 可以使用zip把两个list打包 , 类似: list1 = [1,2,3,4] lis ...

  4. 水管工游戏:dfs(递归)

    添柴网这题好想不能评测,所以不确保代码的正确性 题目描述: 这小节有点难,看不太懂可以跳过哦.最近小哼又迷上一个叫做水管工的游戏.游戏的大致规则是这样的.一块矩形土地被分为N * M的单位正方形,现在 ...

  5. LeetCode 145 ——二叉树的后序遍历

    1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 递归得到其左子树的数据向量 temp,将 temp 合并到 data 中去 递归得到 ...

  6. dice2win

    触发交易 转0个 https://etherscan.io/tx/0x784e80167353a886183106cbe3bd15e614cafdb5d6885ccd101177aa0f937a36 ...

  7. Python3 数值类型与运算符

    1.数值类型与进制 (1)基本类型 整型:int 浮点型:float 布尔类型:bool 复数:complex print(type(1)) print(type(1.1)) print(type(F ...

  8. 1.安装hbase

    参考:http://hbase.apache.org/book.html#quickstart 一.下载hbase 去apache下载hbase,然后解压到/usr/local/hbase-1.1.3 ...

  9. POJ 3845 Fractal(计算几何の旋转缩放)

    Description Fractals are really cool mathematical objects. They have a lot of interesting properties ...

  10. HDU 1042 N!(高精度乘)

    Problem Description Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!   Input One N in ...