DP+斜率优化


  首先我们根据这个分割的过程可以发现:总得分等于k+1段两两的乘积的和(乘法分配律),也就是说与分割顺序是无关的。

  再对乘积进行重分组(还是乘法分配律)我们可以转化为:$ans=\sum$第 i 段×前 i-1 段的和

  所以我们就可以以分割次数为阶段进行DP啦~

  令f[i][j]表示将前 j 个数分成 i 段的最大得分,那么就有$$f[i][j]=max\{ f[i-1][k]+sum[k]×(sum[j]-sum[k]) \}$$我们观察到这个式子其实是很像斜率优化的……而且sum明显满足单调性!所以来推一下决策单调性的式子=。=

  当决策k1<k2时:

  $$ \begin{aligned} f[i-1][k1]+sum[k1]*(sum[j]-sum[k1]) &< f[i-1][k2]+sum[k2]*(sum[j]-sum[k2]) \\ sum[j]*(sum[k1]-sum[k2]) &< f[i-1][k2]-f[i-1][k1]+sum[k1]^2-sum[k2]^2 \\ sum[j] &> \frac{f[i-1][k2]-f[i-1][k1]+sum[k1]^2-sum[k2]^2}{sum[k1]-sum[k2]} \end{aligned}$$

  这题我被坑在:$sum[k1]-sum[k2]\leq 0$!!!

  所以搞斜率的时候,分母可能为0……所以就不能写成斜率的形式,而是搞成上一行那种……但是由于有个负数,所以还要仔细考虑不等号的方向!QAQ

 /**************************************************************
Problem: 3675
User: Tunix
Language: C++
Result: Accepted
Time:18176 ms
Memory:5180 kb
****************************************************************/ //BZOJ 3675
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=1e5+,INF=~0u>>;
typedef long long LL;
/******************tamplate*********************/
LL f[][N],a[N],sum[N];
int from[N],n,m,q[N];
double slope(int i,int j,int k){
i=i&;
return double(f[i][k]-f[i][j]+sum[j]*sum[j]-sum[k]*sum[k]);
}
int main(){
#ifndef ONLINE_JUDGE
freopen("3675.in","r",stdin);
freopen("3675.out","w",stdout);
#endif
n=getint(); m=getint();
F(i,,n) a[i]=getint(),sum[i]=sum[i-]+a[i];
F(i,,m){
int now=i&;
int l=,r=-; q[]=;
F(j,,n){
while(l<r && slope(i-,q[l],q[l+])>=sum[j]*(sum[q[l]]-sum[q[l+]])) l++;
int t=q[l];
f[now][j]=f[now^][t]+sum[t]*(sum[j]-sum[t]);
while(l<r && slope(i-,q[r-],q[r])*(sum[q[r]]-sum[j])>=slope(i-,q[r],j)*(sum[q[r-]]-sum[q[r]])) r--;
q[++r]=j;
}
}
printf("%lld\n",f[m&][n]);
return ;
}

3675: [Apio2014]序列分割

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 541  Solved: 202
[Submit][Status][Discuss]

Description

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

Input

输入文件的第一行包含两个整数n和尼(k+1≤n)。
第二行包含n个非负整数a1,n2….,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)。

Source

[Submit][Status][Discuss]

【BZOJ】【3675】【APIO2014】序列分割的更多相关文章

  1. 【斜率DP】BZOJ 3675:[Apio2014]序列分割

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1066  Solved: 427[Submit][Statu ...

  2. BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )

    WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...

  3. bzoj 3675 [Apio2014]序列分割(斜率DP)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3675 [题意] 将n个数的序列分割k次,每次的利益为分割后两部分数值和的积,求最大利益 ...

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

    题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...

  5. 动态规划(斜率优化):BZOJ 3675 [Apio2014]序列分割

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

  6. bzoj 3675: [Apio2014]序列分割

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

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

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

  8. bzoj 3675: [Apio2014]序列分割【斜率优化dp】

    首先看这个得分方式,容易发现就相当于分k段,每段的值和两两乘起来. 这样就很容易列出dp方程:设f[i][j]为到j分成分成i段,转移是 \[ f[i][j]=max { f[k][j]+s[k]*( ...

  9. BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度

    Code: #include<bits/stdc++.h> #define N 100006 #define M 205 #define ll long long #define setI ...

  10. 3675: [Apio2014]序列分割

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

随机推荐

  1. java字符串解析

    java的虚拟机在内存中开辟出一块单独的区域,用来存储字符串对象,这款内存区域被称为字符串缓冲池. //创建字符串的时候先查找字符串缓冲池中没相同的对象,如果相同的对象就直接返回改对象的引用 //如果 ...

  2. Java反射在Android中的使用

    转载请注明出处:http://www.cnblogs.com/cnwutianhao/p/6606687.html 做Java开发或者安卓开发的同学经常都会遇到这样一个问题,如果我们想调用A类里面的一 ...

  3. html5那些事儿

    一.优势1.标签的改变:<header>,<footer>,<dialog>,<aside>,<figure>,<section> ...

  4. 清北冬令营入学测试[ABCDEF]

    http://tyvj.cn/Contest/861 [1.2.2017] 像我这种蒟蒻只做了前6道还有道不会只拿了暴力分 A 描述 这是一道有背景的题目,小A也是一个有故事的人.但可惜的是这里纸张太 ...

  5. [BZOJ4592][SHOI2015]脑洞治疗仪(线段树)

    线段树基础操作题,唯一需要思考下的是将区间的前k个0覆盖为1. 线段树上二分,先递归到左子树覆盖,回溯时返回还剩多少个0未被覆盖,在根据这个信息递归到右子树.注意特判k=0的情况. 要维护的信息有:区 ...

  6. Windows 0day成功验证之ETERNALBLUE

    本帖由春秋首发~作者:神风 @春秋文阁负责人 方程式又一波0day[该贴有工具]:https://bbs.ichunqiu.com/thread-21736-1-1.html 最近一段时间出现一波高潮 ...

  7. java后台接收json数据,报错com.alibaba.fastjson.JSONObject cannot be cast to xxx

    从前台接收json封装的list数据,在后台接收时一直报错,com.alibaba.fastjson.JSONObject cannot be cast to xxx, 使用这种方式接收可以接收 @R ...

  8. bzoj 2850

    比较基础的KD树.每个节点维护一个BOX,包含包含当当前子树的点的最小矩形,以及点权和,然后用“整个矩形都在直线的一侧”和“整个矩形都不在直线的一侧”剪枝. /******************** ...

  9. SDWebImage支持WebP格式图片

    SDWebImage本身就已经支持了webp格式的图片 1.下载libwebp https://github.com/webmproject/libwebp 然后你需要先安装好有homebrew或者m ...

  10. SMACH专题(四)----状态State类的实现和中文注释

    SMACH中,状态(State)是状态机器组成的重要部分,理解State的原理和实现,对使用SMACH很有帮助,特别是理解 __init__(),execute(),preempt是尤为关键. __i ...