P3648 [APIO2014]序列分割

题目描述

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

选择一个有超过一个元素的块(初始时你只有一块,即整个序列)

选择两个相邻元素把这个块从中间分开,得到两个非空的块。

每次操作后你将获得那两个新产生的块的元素和的乘积的分数。你想要最大化最后的总得分。

输入输出格式

输入格式:

第一行包含两个整数\(n\)和\(k\)。保证\(k + 1 \leq n\)。

第二行包含\(n\)个非负整数\(a_1, a_2, \cdots, a_n(0 \leq a_i \leq 10^4)\),表示前文所述的序列。

输出格式:

第一行输出你能获得的最大总得分。

第二行输出\(k\)个介于\(1\)到\(n - 1\)之间的整数,表示为了使得总得分最大,你每次操作中分开两个块的位置。第\(i\)个整数\(s_i\)表示第\(i\)次操作将在\(s_i\)和\(s_{i+1}\)之间把块分开。

如果有多种方案使得总得分最大,输出任意一种方案即可。

说明

第一个子任务共 11 分,满足 \(1 \leq k < n \leq 10\)。

第二个子任务共 11 分,满足 \(1 \leq k < n \leq 50\)。

第三个子任务共 11 分,满足 \(1 \leq k < n \leq 200\)。

第四个子任务共 17 分,满足 \(2 \leq n \leq 1000, 1 \leq k \leq \min\{n - 1, 200\}\)。

第五个子任务共 21 分,满足 \(2 \leq n \leq 10000, 1 \leq k \leq \min\{n - 1, 200\}\)。

第六个子任务共 29 分,满足 \(2 \leq n \leq 100000, 1 \leq k \leq \min\{n - 1, 200\}\)。


首先得玩出我们不需要做区间DP

因为切的顺序并不影响结果

然后令\(dp[i][j]\)代表前\(i\)个切\(j\)次的最大得分

\(dp[i][j]=max_{j \le k < i}(dp[k][j-1]+f[k] \times (f[i]-f[k]))\)

开\(k\)个单调队列进行斜率优化(事实上一个就够了而我比较傻)

添加时其实很耐人寻味哦


Code:

#include <cstdio>
#define ll long long
ll min(ll x,ll y){return x<y?x:y;}
const int N=100010;
const int M=202;
ll dp[N][M],q[M][N],pre[N][M],l[M],r[M],f[N],n,k;
int ans[M],cnt=0;
ll Y(ll i,ll j)
{
return dp[i][j-1]-f[i]*f[i];
}
ll X(ll i)
{
return f[i];
}
ll K(ll i)
{
return -f[i];
}
int main()
{
//freopen("3675.in","r",stdin);
//freopen("3675.out","w",stdout);
scanf("%lld%lld",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%lld",f+i);
f[i]+=f[i-1];
}
for(int i=1;i<=k;i++)
{
q[i][++r[i]]=1;
++l[i];
}
for(int i=2;i<=n;i++)
for(int j=1;j<=min(i,k+1);j++)
{
while(l[j]<r[j]&&K(i)*(X(q[j][l[j]+1])-X(q[j][l[j]]))
<=(Y(q[j][l[j]+1],j)-Y(q[j][l[j]],j))) l[j]++;
dp[i][j]=dp[q[j][l[j]]][j-1]+f[q[j][l[j]]]*(f[i]-f[q[j][l[j]]]);
pre[i][j]=q[j][l[j]];
while(l[j]<r[j]&&(Y(i,j)-Y(q[j][r[j]],j))*(X(q[j][r[j]])-X(q[j][r[j]-1]))
>=(X(i)-X(q[j][r[j]]))*(Y(q[j][r[j]],j)-Y(q[j][r[j]-1],j))) r[j]--;
q[j][++r[j]]=i;
}
printf("%lld\n",dp[n][k]);
int pos=n,cut=k;
while(cut)
{
pos=pre[pos][cut--];
ans[++cnt]=pos;
}
for(int i=cnt;i;i--)
printf("%d ",ans[i]);
return 0;
}

2018.7.25

洛谷 P3648 [APIO2014]序列分割 解题报告的更多相关文章

  1. 洛谷P3648 [APIO2014]序列分割(斜率优化)

    传送门 没想到这种多个状态转移的还能用上斜率优化……学到了…… 首先我们可以发现,切的顺序对最终答案是没有影响的 比方说有一个序列$abc$,每一个字母都代表几个数字,那么先切$ab$再切$bc$,得 ...

  2. 洛谷 P3648 [APIO2014]序列分割

    题意简述 有一个长度为n的序列,分成k + 1非空的块, 选择两个相邻元素把这个块从中间分开,得到两个非空的块. 每次操作后你将获得那两个新产生的块的元素和的乘积的分数.求总得分最大值. 题解思路 f ...

  3. 洛谷3648 [APIO2014]序列分割(斜率优化+dp)

    首先对于这个题目. qwq 存在一个性质就是,最终的答案只跟你的分割的位置有关,而和顺序无关. 举一个小栗子 \(a\ b\ c\) 将这个东西分成两块. 如果我们先分割\(ab\)之间的话,\(an ...

  4. P3648 [APIO2014]序列分割(斜率优化dp)

    P3648 [APIO2014]序列分割 我们先证明,分块的顺序对结果没有影响. 我们有一个长度为3的序列$abc$ 现在我们将$a,b,c$分开来 随意枚举一种分块方法,如$(ab)(c)$,$(a ...

  5. [luogu P3648] [APIO2014]序列分割

    [luogu P3648] [APIO2014]序列分割 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序 ...

  6. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  7. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

  8. 洛谷 P3802 小魔女帕琪 解题报告

    P3802 小魔女帕琪 题目背景 从前有一个聪明的小魔女帕琪,兴趣是狩猎吸血鬼. 帕琪能熟练使用七种属性(金.木.水.火.土.日.月)的魔法,除了能使用这么多种属性魔法外,她还能将两种以上属性组合,从 ...

  9. 洛谷 P2606 [ZJOI2010]排列计数 解题报告

    P2606 [ZJOI2010]排列计数 题目描述 称一个\(1,2,...,N\)的排列\(P_1,P_2...,P_n\)是\(Magic\)的,当且仅当对所以的\(2<=i<=N\) ...

随机推荐

  1. jquery Ajax请求中显示Loading...

    jquery Ajax请求中显示Loading... $('#btnTest').click(function(){      $.ajax({           url ---- ,根据你需要设置 ...

  2. 第四篇 前端学习之JQuery基础

    一 jQuery是什么? jQuery就是一个JavaScript的库. <1> jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入 ...

  3. Lua学习笔记(8): 元表

    元表 Lua中提供了元表(Metatable),其实这个元表就比较像面向对象中的类了,可以通过给某些特殊的标识符赋值达到重载的效果,这些特殊的标识符有: 名称 功能 __index 元表的索引方法 _ ...

  4. header field token is not allowed by Access-Control-Allow-Headers in preflight response问题解决

    今天下午,本来打算使用aioxs在header里传一个token给后台服务器,如下图所示: 结果,控制台报了如下的错: 然后,我不停地百度,不停的改后台express的header设置,一直没有效果: ...

  5. grunt requireJS 的基础配置

    module.exports = function(grunt){ //grunt的配置我就不叨叨了 自己看官网就ok了 //我就介绍下grunt的依赖插件grunt-contrib-requirej ...

  6. 如何让QT程序以管理员权限运行(UAC)

    方案一:(仅适用于使用msvc编译器) 在PRO文件中添加一行指令即可, QMAKE_LFLAGS += /MANIFESTUAC:"level='requireAdministrator' ...

  7. Material Safety Data Sheet,MSDS - 化学品安全说明书

    化学品安全说明书(Material Safety Data Sheet)MSDS,国际上称作化学品安全信息卡,是化学品生产商和经销商按法律要求必须提供的化学品理化特性(如PH值,闪点,易燃度,反应活性 ...

  8. Python:字符串操作总结

    所有标准的序列操作(索引.分片.乘法.判断成员资格.求长度.取最小值最大值)对字符串同样适用,且字符串是不可变的. 一.字符串格式化 转换说明符 [注]: 这些项的顺序至关重要 (1)%字符:标记转换 ...

  9. 0429团队项目-Scrum团队成立

    Scrum团队成立 团队名称:开拓者 团队目标:努力让每一个小伙伴在学会走路的基础上学会跑. 团队口号:我们要的只是这片天而已. 团队照:正面照+背影照(那就是为什么组名叫开拓者) 5.2 角色分配 ...

  10. 获取emacs安装的elpa包名称

    | grep "./" | sed 's/\.\///g' | sed 's/-[0-9].*$//' | sort -u