2019杭电多校第三场hdu6606 Distribution of books(二分答案+dp+权值线段树)
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+权值线段树)的更多相关文章
- [2019杭电多校第三场][hdu6606]Distribution of books(线段树&&dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6606 题意为在n个数中选m(自选)个数,然后把m个数分成k块,使得每块数字之和最大的最小. 求数字和最 ...
- 2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)
K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明 ...
- [2019杭电多校第三场][hdu6609]Find the answer(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6609 大致题意是求出每个位置i最小需要将几个位置j变为0(j<i),使得$\sum_{j=1}^ ...
- [2019杭电多校第三场][hdu6608]Fansblog
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6608 大致题意是比p小的最大素数q,求q!%p的值. 由威尔逊定理开始推: $(p-1)!\equiv ...
- 2019杭电多校第三场hdu6608 Fansblog(威尔逊定理)
Fansblog 题目传送门 解题思路 Q! % P = (P-1)!/(P-1)...(Q-1) % P. 因为P是质数,根据威尔逊定理,(P-1)!%P=P-1.所以答案就是(P-1)((P-1) ...
- 2019杭电多校第三场hdu6609 Find the answer(线段树)
Find the answer 题目传送门 解题思路 要想变0的个数最少,显然是优先把大的变成0.所以离散化,建立一颗权值线段树,维护区间和与区间元素数量,假设至少减去k才能满足条件,查询大于等于k的 ...
- HDU多校第三场 Hdu6606 Distribution of books 线段树优化DP
Hdu6606 Distribution of books 题意 把一段连续的数字分成k段,不能有空段且段和段之间不能有间隔,但是可以舍去一部分后缀数字,求\(min(max((\sum ai ))\ ...
- 2019年杭电多校第三场 1011题Squrirrel(HDU6613+树DP)
题目链接 传送门 题意 给你一棵无根树,要你寻找一个根节点使得在将一条边权变为\(0\)后,离树根最远的点到根节点的距离最小. 思路 本题和求树的直径很像,不过要记得的东西有点多,且状态也很多. \( ...
- 2019年杭电多校第三场 1008题Game(HDU6610+带修改莫队+Nim博弈)
题目链接 传送门 题意 给你\(n\)堆石子,每堆有\(a_i\)堆石子,\(q\)次操作: 在\([L,R]\)内有多少个子区间使得\(Alice\)(先手)在\(Nim\)博弈中获胜: 交换\(a ...
随机推荐
- Redis入门很简单之五【Jedis和Spring的整合】
Redis入门很简单之五[Jedis和Spring的整合] 博客分类: NoSQL/Redis/MongoDB redisnosql缓存jedisspring 在上一篇文章中,简单介绍了Jedis的 ...
- windows10下Mysql5.7安装指南
背景 值此国庆70周年之际,为了发扬广大国内软件开发行业,我决定使用MySQL5.7. 呸!实际情况是公司的项目用的是Mysql5.7,但是正式服务器在国外,而且测试服务器也是在国外,关键问题是我这个 ...
- sqlserver2012分页注意事项
SELECT orderid, orderdate, custid, empid FROM Sales.Orders ORDER BY orderdate, orderid OFFSET 600 RO ...
- 用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览
#目录 前文列表 扩展阅读 Jinja 变量名 注释 控制语句 if 语句 循环 过滤器 无参数调用 带参数调用 宏 定义宏 调用宏 结果 兼容 JavaScript 前文列表 用 Flask 来写个 ...
- JS对象中属性的增删改查
对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性 对象的分类: 1.内建对象 -在ES标准中定义的对象,在任何的ES的实现中都可以 ...
- 力扣算法——136SingleNumber【E】
Given a non-empty array of integers, every element appears twice except for one. Find that single on ...
- leetcode.数组.565数组嵌套-Java
1. 具体题目 索引从0开始长度为N的数组A,包含0到N - 1的所有整数.找到并返回最大的集合S,S[i] = {A[i], A[A[i]], A[A[A[i]]], ... }且遵守以下的规则.假 ...
- Python之Tab键自动补全
首先备份一下Tab键自动补全代码: # python start file import sys import readline import rlcompleter import atexit im ...
- 初探remoting双向通信(一)
原 初探remoting双向通信(一) 2013年06月24日 15:47:07 喜欢特别冷的冬天下着雪 阅读数 4389 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- Rendering Problems The following classes could not be found:- android.support.v7.internal.app.WindowDecorActionBar (Fix Build Path, Create Class)
如图出现如下的错误的时候,一般都是升级Androdi Studio 后导致的,引入库不全,或者其他 东西缺少 可以如下解决方案: