题意:给你一个序列,你可以选择序列的一个前缀,把前缀分成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);
}
}

  

2019HDU多校第三场 Distribution of books 二分 + DP的更多相关文章

  1. 2019HDU多校第三场F Fansblog——威尔逊定理&&素数密度

    题意 给定一个整数 $P$($10^9 \leq p\leq 1^{14}$),设其前一个质数为 $Q$,求 $Q!  \ \% P$. 分析 暴力...说不定好的板子能过. 根据威尔逊定理,如果 $ ...

  2. 2019HDU多校第三场 K subsequence——最小费用最大流

    题意 给定一个 $n$ 个整数的数列,从中至多选取 $k$ 个上升子序列(一个元素最多被选一次),使得选取的元素和最大. 分析 考虑这个问题和经典网络流问题“最长不下降子序列”相似,我们考虑对这个建图 ...

  3. [2019HDU多校第三场][HDU 6603][A. Azshara's deep sea]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6603 题目大意:给出一个凸包,凸包内有若干个圆,要求画尽可能多的对角线使得他们两两不在凸包内相交且不与 ...

  4. 2019Hdu多校第三场:1007 Find the answer(multiset 解法)

    原题链接: Find the answer c++中,multiset是库中一个非常有用的类型,它可以看成一个序列,插入一个数,删除一个数都能够在O(logn)的时间内完成,而且他能时刻保证序列中的数 ...

  5. 2018杭电多校第三场1003(状态压缩DP)

    #include<bits/stdc++.h>using namespace std;const int mod =1e9+7;int dp[1<<10];int cnt[1& ...

  6. 2018 HDU多校第三场赛后补题

    2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...

  7. 牛客多校第三场 F Planting Trees

    牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...

  8. 牛客多校第三场 G Removing Stones(分治+线段树)

    牛客多校第三场 G Removing Stones(分治+线段树) 题意: 给你n个数,问你有多少个长度不小于2的连续子序列,使得其中最大元素不大于所有元素和的一半 题解: 分治+线段树 线段树维护最 ...

  9. 2019杭电多校第三场hdu6606 Distribution of books(二分答案+dp+权值线段树)

    Distribution of books 题目传送门 解题思路 求最大值的最小值,可以想到用二分答案. 对于二分出的每个mid,要找到是否存在前缀可以份为小于等于mid的k份.先求出这n个数的前缀和 ...

随机推荐

  1. [前端自动化]grunt的简单使用

    前言 现在前端自动化已经是家常便饭,各种工具也是层出不穷,grunt.gulp.webpack是应用最广的三种工具,虽然grunt看似已垂垂老矣,但是以前写的很多项目一直用的就是grunt,温故方能知 ...

  2. java一个对象使用内存

  3. jmeter 参数化2_CSV Data Set Config

    CSV Data Set Config:适用于参数取值范围较大的时候使用,该方法具有更大的灵活性 操作路径:HTTP取样器-->Add-->Config Element-->CSV ...

  4. python 的set定义

    set是集合,跟数学中的集合一样不能重复没有顺序 set定义有两种方式 1. b=set([1, 2, 3, 4]) 2. a={"} 输出: b=set([1, 2, 3, 4])a={1 ...

  5. macOS 和 Linux 的内核区别

    有些人可能会认为 macOS 和 Linux 内核之间存在相似之处,因为它们可以处理类似的命令和类似的软件.有些人甚至认为苹果公司的 macOS 是基于 Linux 的.事实上是,两个内核有着截然不同 ...

  6. 【HDOJ6578】Blank(DP)

    题意:一个长为n的序列,每个位置上的值是0,1,2,3中的一个,有m个限制条件,限制位置[l[i],r[i]]中不同的数值有x[i]个,问方案数MOD 998244353 n<=100,m< ...

  7. Vue.js 计算属性

    Vue.js 计算属性 使用计算属性的实例: <!DOCTYPE html> <html> <head> <meta cahrset="utf-8& ...

  8. php 封装原生数据导出的方法(csv文件格式)和csv文件中长数字自动变成科学计数法的处理

    如何解决上图长数字自动转换处理? CSV文件中长数字自动变成科学计数法处理.用程序导出的csv文件,当字段中有比较长的数字字段存在时,在用excel软件查看csv文件时就会变成科学计数法的表现形式. ...

  9. 51单片机的idata,xdata,pdata,data的详解

    data: 固定指前面0x00-0x7f的128个RAM,可以用acc直接读写的,速度最快,生成的代码也最小. bit :是指0x20-0x2f的可位寻址区idata:固定指前面0x00-0xff的2 ...

  10. Asynchronous C# server[转]

    It hasn't been thoroughly tested, but seems to work OK. This should scale pretty nicely as well. Ori ...