Distribution of books

题目传送门

解题思路

求最大值的最小值,可以想到用二分答案。

对于二分出的每个mid,要找到是否存在前缀可以份为小于等于mid的k份。先求出这n个数的前缀和sum[],dp[i]表示前i个可以构成的最大份数。初始化dp[1~n]为-1,dp[0]为0,转移方程式为:dp[i] = max(dp[j]) + 1,(sum[i] - sum[j] <= mid, dp[j] >= 0, 0 <= j < i)。如果有一个dp[i]>=k,说明mid可以,r=mid,否则l=mid+1。

但是数据范围很大,直接这么找肯定超时。所以我们要用离散化后的权值线段树来维护。对于i,我们要找的是满足sum[i] - sum[j] <= mid,即sum[j] >= sum[i] - mid的j里最大的dp[j]。所以我们用权值线段树来来维护前i-1个dp的最大值。对于每次二分都清空然后重新建树,按照插入dp[i],对于每次询问只需返回离散化后sum[j]~最大值的范围内的最大dp值。

代码如下

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll; inline int read(){
int res = 0, w = 0; char ch = 0;
while(!isdigit(ch)){
w |= ch == '-', ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -res : res;
} const int N = 200005; ll a[N], b[N];
struct T{
int l, r;
int maxx;
}tree[N<<2];
int dp[N];
int n, m; void build(int k, int l, int r)
{
tree[k].l = l;
tree[k].r = r;
tree[k].maxx = -1;
if(l >= r)
return;
int mid = (l + r) / 2;
build(2*k, l, mid);
build(2*k+1, mid + 1, r);
} void insert(int k, int x, int u)
{
if(tree[k].l == tree[k].r){
tree[k].maxx = max(tree[k].maxx, u);
return;
}
int mid = (tree[k].l + tree[k].r) / 2;
if(x <= mid)
insert(2*k, x, u);
else
insert(2*k+1, x, u);
tree[k].maxx = max(tree[2*k].maxx, tree[2*k+1].maxx);
} int query(int k, int l, int r)
{
if(tree[k].l >= l && tree[k].r <= r)
return tree[k].maxx;
int mid = (tree[k].l + tree[k].r) / 2;
int m1, m2;
m1 = m2 = -1;
if(l <= mid)
m1 = query(2*k, l, r);
if(r > mid)
m2 = query(2*k+1, l, r);
return max(m1, m2);
} bool work(ll mid, int k)
{
build(1, 0, k);
insert(1, lower_bound(b, b + k + 1, 0) - b, 0);
for(int i = 1; i <= n; i ++){
int l = lower_bound(b, b + k + 1, a[i] - mid) - b;
if(l != k + 1)
dp[i] = query(1, l, k)+ 1;
else
dp[i] = -1;
if(dp[i] == 0)
dp[i] = -1;
if(dp[i] >= m)
return true;
int x = lower_bound(b, b + k + 1, a[i]) - b;
insert(1, x, dp[i]);
}
return false;
} int main()
{
int _ = read();
while(_ --){
n = read(), m = read();
ll l = 0, r = 0;
a[0] = b[0] = 0;
for(int i = 1; i <= n; i ++){
ll x = read();
if(x < 0)
l += x;
if(x > 0)
r += x;
a[i] = a[i - 1] + x;
b[i] = a[i];
}
sort(b, b + n + 1);
int k = unique(b, b + n + 1) - b - 1;
ll mid = (l + r) / 2;
while(l < r){
if(work(mid, k))
r = mid;
else
l = mid + 1;
mid = (l + r) / 2;
}
printf("%lld\n", mid);
}
return 0;
}

2019杭电多校第三场hdu6606 Distribution of books(二分答案+dp+权值线段树)的更多相关文章

  1. [2019杭电多校第三场][hdu6606]Distribution of books(线段树&&dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6606 题意为在n个数中选m(自选)个数,然后把m个数分成k块,使得每块数字之和最大的最小. 求数字和最 ...

  2. 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

    K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...

  3. [2019杭电多校第三场][hdu6609]Find the answer(线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6609 大致题意是求出每个位置i最小需要将几个位置j变为0(j<i),使得$\sum_{j=1}^ ...

  4. [2019杭电多校第三场][hdu6608]Fansblog

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6608 大致题意是比p小的最大素数q,求q!%p的值. 由威尔逊定理开始推: $(p-1)!\equiv ...

  5. 2019杭电多校第三场hdu6608 Fansblog(威尔逊定理)

    Fansblog 题目传送门 解题思路 Q! % P = (P-1)!/(P-1)...(Q-1) % P. 因为P是质数,根据威尔逊定理,(P-1)!%P=P-1.所以答案就是(P-1)((P-1) ...

  6. 2019杭电多校第三场hdu6609 Find the answer(线段树)

    Find the answer 题目传送门 解题思路 要想变0的个数最少,显然是优先把大的变成0.所以离散化,建立一颗权值线段树,维护区间和与区间元素数量,假设至少减去k才能满足条件,查询大于等于k的 ...

  7. HDU多校第三场 Hdu6606 Distribution of books 线段树优化DP

    Hdu6606 Distribution of books 题意 把一段连续的数字分成k段,不能有空段且段和段之间不能有间隔,但是可以舍去一部分后缀数字,求\(min(max((\sum ai ))\ ...

  8. 2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)

    题目链接 传送门 题意 给你一棵无根树,要你寻找一个根节点使得在将一条边权变为\(0\)后,离树根最远的点到根节点的距离最小. 思路 本题和求树的直径很像,不过要记得的东西有点多,且状态也很多. \( ...

  9. 2019年杭电多校第三场 1008题Game(HDU6610+带修改莫队+Nim博弈)

    题目链接 传送门 题意 给你\(n\)堆石子,每堆有\(a_i\)堆石子,\(q\)次操作: 在\([L,R]\)内有多少个子区间使得\(Alice\)(先手)在\(Nim\)博弈中获胜: 交换\(a ...

随机推荐

  1. HTML-参考手册: HTML 字符集

    ylbtech-HTML-参考手册: HTML 字符集 1.返回顶部 1. HTML 字符集 HTML 字符集 如需正确地显示 HTML 页面,浏览器必须知道使用何种字符集. 万维网早期使用的字符集是 ...

  2. 为什么重写equals还要重写hashcode

    参考回答: HashMap中,如果要比较key是否相等,要同时使用这两个函数!因为自定义的类的hashcode()方法继承于Object类,其hashcode码为默认的内存地址,这样即便有相同含义的两 ...

  3. NIO浅析(一)

    一:NIO与IO的区别 1.NIO面对的是缓冲区,IO面对的是流 2.NIO是非阻塞的,IO是阻塞的 3.NIO中引入了选择器 二:既然NIO面对的是缓冲区,那就先来了解缓冲区 1.NIO中Buffe ...

  4. PHP中使用raw格式发送POST请求

    如果请求的参数格式是原生(raw)的内容,应该如何为程序构造一个POST请求函数呢? function http_post($url, $data_string) { $ch = curl_init( ...

  5. 使用IDEA快速搭建Springboot项目

    Spring Boot是由Pivotal团队提供的全新框架,设计目的是用来简化新Spring应用的初始搭建以及开发过程.它主要推崇的是'消灭配置’,实现零配置. 下面就介绍一下如何使用idea快速搭建 ...

  6. github中fork分支和pullrequest的最佳实践

    github中fork分支和pullrequest的最佳实践 */--> code {color: #FF0000} pre.src {background-color: #002b36; co ...

  7. android 自定义标题

    public class MainActivity extends Activity { /** Called when the activity is first created. */ @Over ...

  8. vue组件库的基本开发步骤

    市面上目前已有各种各样的UI组件库,比如 Element 和 iView,他们的强大毋庸置疑.但是我们面临的情况是需求越来越复杂,当它们不能再满足我们需求的时候,这个时候就有必要开发一套属于自己团队的 ...

  9. CSS 中 transform、animation、transition、translate的区别

    在前端页面的开发过程中,经常会碰到这么几个 CSS 属性容易搞混:transform.translate.animation还有transition.下面就针对这几个 CSS 属性做一个对比,辨别这几 ...

  10. Leetcode 200.岛屿的数量 - DFS、BFS

    Leetcode 200 岛屿的数量: DFS利用函数调用栈保证了检索顺序, BFS则需要自己建立队列,把待检索对象按规则入队. class Solution { // DFS解法,8ms/10.7M ...