题意:给你一个序列,你可以选择序列的一个前缀,把前缀分成k个连续的部分,要求这k个部分的区间和的最大值尽量的小,问这个最小的最大值是多少?

思路:首先看到最大值的最小值,容易想到二分。对于每个二分值mid,我们判断原序列是否可以构成k个区间和小于等于mid的区间,这个可以用DP来做。我们先求出序列的前缀和,这样可以把区间和变成前缀相减的形式。之后,对于当前的前缀和sum[i], 我们找前缀和大于等于sum[i] - mid的状态中dp值最大的向自己转移。如果最后存在状态的dp值大于等于k,那么说明二分的mid值偏大,要缩小上边界。反之亦然。dp用离散化 + 线段树优化,总复杂度O(n * logn) * log(值域)

代码:

#include <bits/stdc++.h>
#define LL long long
#define ls (o << 1)
#define rs (o << 1 | 1)
using namespace std;
const int maxn = 200010;
LL sum[maxn];
LL a[maxn];
LL b[maxn];
int dp[maxn], mx[maxn * 4];
int n, m, tot;
void build(int o, int l, int r) {
if(l == r) {
mx[o] = -1;
return;
}
int mid = (l + r) >> 1;
build(ls, l, mid);
build(rs, mid + 1, r);
mx[o] = max(mx[ls], mx[rs]);
}
void update(int o, int l, int r, int p, int val) {
if(l == r) {
mx[o] = max(mx[o], val);
return;
}
int mid = (l + r) >> 1;
if(p <= mid) update(ls, l, mid, p, val);
else update(rs, mid + 1, r, p, val);
mx[o] = max(mx[ls], mx[rs]);
}
int query(int o, int l, int r, int ql, int qr) {
if(ql > qr) return -1;
if(l >= ql && r <= qr) {
return mx[o];
}
int mid = (l + r) >> 1, ans = -1;
if(ql <= mid) ans = max(ans, query(ls, l, mid, ql, qr));
if(qr > mid) ans = max(ans, query(rs, mid + 1, r, ql, qr));
return ans;
}
bool solve(LL mid) {
build(1, 1, tot);
update(1, 1, tot, lower_bound(b + 1, b + 1 + tot, 0) - b, 0);
for (int i = 1; i <= n; i++) {
int p = lower_bound(b + 1, b + 1 + tot, sum[i] - mid) - b;
int p1 = lower_bound(b + 1, b + 1 + tot, sum[i]) - b;
int tmp = query(1, 1, tot, p, tot);
if(tmp == -1) dp[i] = -1;
else dp[i] = tmp + 1;
if(dp[i] >= m) return 0;
update(1, 1, tot, p1, dp[i]);
}
return 1;
}
int main() {
int T;
// freopen("input.txt", "r", stdin);
// freopen("1.in", "r", stdin);
scanf("%d", &T);
while(T--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%lld", &a[i]);
sum[i] = sum[i - 1] + a[i];
b[i] = sum[i];
}
b[n + 1] = 0;
sort(b + 1, b + 1 + n + 1);
tot = unique(b + 1, b + 1 + n + 1) - (b + 1);
LL l = -2e14, r = 2e14;
while(l < r) {
LL mid = (l + r) >> 1;
if(solve(mid)) l = mid + 1;
else r = mid;
}
printf("%lld\n", l);
}
}

  

最新文章

  1. 为什么Java不适合游戏开发
  2. java三篇博客转载 详解-vector,stack,queue,deque
  3. Java中this、super用法
  4. java-testng-selenium优化
  5. mybatis系列-13-resultMap总结
  6. [LeetCode#159] Missing Ranges Strobogrammatic Number
  7. 为Chrome添加https搜索 自定义地址栏搜索引擎
  8. chromium for android v34 2dcanvas硬件渲染实现分析
  9. 多线程学习之一独木桥模式Single Threaded Execution Pattern
  10. [转]View属性 之 paddingStart &amp; paddingEnd
  11. Kinect 常用识别手势
  12. 实战-Mysql主从复制
  13. Python爬虫与一汽项目【三】爬取中国五矿集团采购平台
  14. redis&#160;redis常用命令及内存分析总结(附RedisClient工具简介
  15. spring cloud Eureka常见问题总结
  16. grid - 通过网格区域命名和定位网格项目
  17. 虚拟树研究-CheckBox初步判断只能在第一列
  18. 1.7Oob 构造方法
  19. jquery 请求返回的几种方式
  20. 【Anroid】9.1 ListView相关类及其适配器

热门文章

  1. Android使用gradle依赖管理、依赖冲突终极解决方案(转)
  2. 190行代码实现mvvm模式
  3. 微信小程序中的自定义组件 以及 相关的坑
  4. 查看mysql数据库文件存放位置
  5. WORM Worm worm 毛毛虫爬树爬树~
  6. [CSP-S模拟测试]:Race(数学+Trie树)
  7. [CSP-S模拟测试]:阴阳(容斥+计数+递推)
  8. Configuring IPMI under Linux using ipmitool
  9. java ee项目用gradle依赖打包
  10. jenkins-参数化构建插件:Choice Parameter