题意

有一个非负整数序列\({a_i}\),你要将他分成恰好\(k\)段,记\(s_i\)为第\(i\)段的和,\(m_i\)为第\(i\)段的最大值,你需要保证这种划分方案对任意\(1 \le i < k\)满足:\(|s_i-s_{i+1}|\le \max(m_i,m_{i+1})\)

\(3 \leq k \leq n \leq 100\,000\)

传送门

思路

题解中的给出的分割为和的平方最小的,请自星阅读,其实最终实现方法也可以互通

我们定义“对序列进行一次\(x\)划分”为(从前往后或从后往前)扫一遍序列,每当权值和大于等于\(x\)就分一段。

二分出最大的\(x\)满足划分后段数\(\ge k\)(注意不算最后的和不到的零头段),令其为\(mid\)。

如果对序列进行\(mid\)划分后序列被恰好分成了\(k\)段,那么这种划分方案在原问题下就是最优的且合法的。

证明:考虑两段划分,\(mid-x_i\)表示除最后一个外的和(\(x_i >0\)),那么\(mid-x_i+last_i-(mid-x_{i+1}+last_{i+1})\le last_i \leq m_i\)。所以一定是小于等于最大值的

若不满足,则可以对序列倒着做\(mid+1\)分段,通过某种方式(这里的证明比较随意,感性理解一下)可以证明正着做\(mid\)分段与倒着做\(mid+1\)分段存在至少一个公共划分点,且满足用前者划分的一段前缀拼上后者划分的一段后缀恰好可以得到原问题的一组合法解。

一波乱证:因为二分出的是最大的答案,\(mid+1\)划分个数\(k-a(a>0)\)肯定小于\(mid\)划分个数\(k+b(b \ge 0)\)

反证

如果没有重合点,那么肯定有一段\(mid+1\)划分会包含\(mid\)划分(左右端点不同的),但是可知\(mid\)划分加上一个正整数(在贪心过程中0不会出现在\(mid\)右端点以及\(mid+1\)左端点,可以忽略)肯定可以\(\ge mid+1\),而这里多加了至少两个数所以矛盾

然后要使加起来个数=k的话每出现一个重合点块数就会-1或-0(一段都重合),不出现就不会,换句话说,每一个使块数\(-1\)的点都是重合点。因为\((l_{mid}<l_{mid+1},r_{mid}<r_{mid+1})\),所以一定能找到一个重合点,使得两者加起来刚好为k

至于代码那是非常的简短,但是这思路也是神仙了

#include <bits/stdc++.h>
typedef long long ll;
const int N=100005;
int n,a[N],p[N],p2[N],k;
long long l,r,ans;
int check(ll x){
ll sum=0;int cnt=0;
for (int i=1;i<=n;i++){
sum=sum+a[i];
if (sum>=x) cnt++,sum=0;
}
return cnt;
}
int main(){
scanf("%d%d",&n,&k);
for (int i=1;i<=n;i++) scanf("%d",&a[i]),r=r+a[i];
while (l<=r){
ll mid=(l+r)>>1;
if (check(mid)>=k){
ans=mid;
l=mid+1;
}else r=mid-1;
}
puts("Yes");
ll sum=0;int cnt=0;
for (int i=1;i<=n;i++){
sum=sum+a[i];
if (sum>=ans) p[++cnt]=i,sum=0;
}
if (p[cnt]==n && cnt==k){
for (int i=1;i<cnt;i++) printf("%d ",p[i]);
puts("");
return 0;
}
sum=0;int cnt2=0;
for (int i=n;i>=1;i--){
sum=sum+a[i];
if (sum>=ans+1) p2[++cnt2]=i,sum=0;
}
for (int i=1;i<=cnt;i++){
if (p[i]==p2[k-i]-1){
for (int j=1;j<=i;j++) printf("%d ",p[j]);
for (int j=k-i-1;j>=1;j--) printf("%d ",p2[j]-1);
puts("");
break;
}
}
return 0;
}

后记

想不到系列

[300iq contest1-J]Jealous Split的更多相关文章

  1. 2016 Al-Baath University Training Camp Contest-1 J

    Description X is fighting beasts in the forest, in order to have a better chance to survive he's gon ...

  2. 300iq Contest 1 简要题解

    300iq Contest 1 简要题解 咕咕咕 codeforces A. Angle Beats description 有一张\(n\times m\)的方阵,每个位置上标有*,+,.中的一种. ...

  3. React使用antd Table生成层级多选组件

    一.需求 用户对不同的应用需要有不同的权限,用户一般和角色关联在一起,新建角色的时候会选择该角色对应的应用,然后对应用分配权限.于是写了一种实现的方式.首先应用是一个二级树,一级表示的是应用分组,二级 ...

  4. 利用poi导出Excel

    import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.r ...

  5. BZOJ3197 & 组合乱搞

    Description    求\[\sum_{i = 1}^{n}i^m m^i , m \leq 1000 \] 的值.Solution    From Miskcoo's Space:      ...

  6. JavaScript状态机程序逻辑编辑器

    制作背景 之前做Win8 Metro动态加载内容框架的时候,由于采用了XAML+JavaScript的方法,程序复杂的执行逻辑是由JavaScript控制的,而页面一多,流程一复杂,制作起来就非常麻烦 ...

  7. Python开发【前端】:JavaScript

    JavaScript入门 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本 ...

  8. Winform-DataGridView 实现如Excel的粘贴复制

    void AddDataGridView(DataGridView gridView, string s) { s = s.Replace("/", @"\") ...

  9. java动手动脑和课后实验型问题String类型

    1.请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? true true false 总结: 使用new关键字创建字符串对象时, 每次申请 ...

随机推荐

  1. Angular使用操作事件指令ng-click传多个参数示例

    本文实例讲述了Angular使用操作事件指令ng-click传多个参数功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html ng-app="m ...

  2. 英语foteball足球历史

    foteball n.足球 现代足球 参见:现代足球 现代足球起源地是在英格兰.传说在11世纪,英格兰与丹麦之间有过一场战争,战争结束后,英格兰人在清理战争废墟时发现一个丹麦入侵者的头骨,出于愤恨,他 ...

  3. Spring Data Jpa 复杂查询总结

    实体类 @Entity @Table(name = "t_hotel") @Data public class THotel { @Id private int id; priva ...

  4. 支付宝支付 微信支付SDK接口不统一? 盘他!

      开发过支付宝.微信支付的同学都知道,微信的支付 API 设计感觉是 Java 开发工程师写的,远不如支付宝 SDK 的接口设计用起来顺手.在这里,统一封装微信支付和支付宝支付的API,使两种支付方 ...

  5. IDEA 导入Module,多个Module在同一个Project 下显示

    之前导入过,隔断时间就忘记了,干脆记下来,免得后续找的麻烦 此文章转载自: https://blog.csdn.net/yyym520/article/details/77527976 1.打开IDE ...

  6. Spark实现二次排序

    一.代码实现 package big.data.analyse.scala.secondsort import org.apache.log4j.{Level, Logger} import org. ...

  7. Jmeter计数器的使用-转载

    说一下jmeter中,配置元件-计数器的使用. 如果需要引用的数据量较大,且要求不能重复或者需要自增,那么可以使用计数器来实现. 1.启动jmeter,添加线程组,右键添加配置元件——计数器,如下图: ...

  8. logstash multiple piplines 配置方式

    当logstash有很多个input类型需要处理时.为了更方便的管理,我们需要使用一个.conf(input->filter->output)配置文件来对应一个pipeline. pipl ...

  9. JS使用Cookie

    包:https://www.npmjs.com/package/js-cookie 一.安装 npm install js-cookie --save 二.引用 import Cookies from ...

  10. Relief 过滤式特征选择

    给定训练集{(x1,y1),(x2,y2).....(xm,ym)} ,对每个示例xi,Relief在xi的同类样本中寻找其最近邻xi,nh(猜中近邻),再从xi的异类样本中寻找其最近邻xi,nm(猜 ...