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. 「日常训练」 Yukari's Birthday(ZOJ-3665)

    题意与分析 二分题.考虑到n的范围是\(10^{12}\),注意到等比公式\(S=a_1\frac{1-q^n}{1-q} (q\ne 1)\),可以看出,不论q有多大(1除外,这个时候\(r=1,k ...

  2. linux部署MantisBT(二)部署php

    二.部署php 1.下载php安装包 http://php.net/downloads.php 2.安装php yum install libxml2 yum install libxml2-deve ...

  3. Java并发基础--volatile关键字

    一.java内存模型 1.java内存模型 程序运行过程中的临时数据是存放在主存(物理内存)中,但是现代计算机CPU的运算能力和速度非常的高效,从内存中读取和写入数据的速度跟不上CPU的处理速度,在这 ...

  4. yarn logs -applicationId命令java版本简单实现

    import java.io.DataInputStream; import java.io.EOFException; import java.io.FileNotFoundException; i ...

  5. 系统滴答定时器(SysTick)中断配置

    系统滴答定时器(SysTick)中断配置 在STM32标准库中是通过SysTick_Config()函数配置时钟中断的,然后SysTick_Handler()函数自动定时触发其中的函数. if(Sys ...

  6. Python3 Tkinter-Label

    1.创建 from tkinter import * root=Tk() root.title('Hello tkinter!') root.mainloop() 2.使用内置位图 from tkin ...

  7. 150命令之线上查询及帮助命令 man hellp

    150命令之线上查询及帮助命令 man 查询命令的帮助 man + 命令 NAME        ls - list directory contents 命令+命令简单说明   SYNOPSIS   ...

  8. HDU 4308 Saving Princess claire_(简单BFS)

    求出不使用P点时起点到终点的最短距离,求出起点到所有P点的最短距离,求出终点到所有P点的最短距离. 答案=min( 不使用P点时起点到终点的最短距离, 起点到P的最短距离+终点到P的最短距离 ) #i ...

  9. UESTC 1717 Journey(DFS+LCA)(Sichuan State Programming Contest 2012)

    Description Bob has traveled to byteland, he find the N cities in byteland formed a tree structure, ...

  10. 常用实例:js格式化手机号为3 4 4形式

    如何在填写手机号时将格式转换为3 4 4形式: 一:填写手机号时,在keyup事件中判断长度,符合条件时在值后面插入空格 $('#username').on('keyup',function(e){ ...