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 ...
随机推荐
- (54) C# 调用 kernel32.dll
https://www.cnblogs.com/cwy173/archive/2010/10/02/1841321.html Kernel32 API AddAtom 向本地原子表添加一个字符串 Al ...
- mysql存储过程、函数、触发器、
当数据库版本不允许直接使用存储过程.函数的语法时用delimiter // 将结束符改成//用完之后再写delimiter;将结束符改回来即可,调用过程.函数用call+其名字即可返回结果 delim ...
- MySQL高级学习笔记(一):mysql简介、mysq linux版的安装(mysql 5.5)
文章目录 MySQL简介 概述 mysql高手是怎样炼成的 mysq linux版的安装(mysql 5.5) 下载地址 拷贝&解压缩 检查工作 检查当前系统是否安装过mysql 检查/tmp ...
- 运维 06 vim与程序员
vim与程序员 所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主动的以 ...
- Linux(二)—— Linux配置及指令
目录 Linux配置及指令 一.linux中常用软件的安装 二.主机名和网络 1.修改主机名 2.设置网络 三.关闭防火墙 1.检查防火墙是否开启 2.清除策略 3.永久关闭第一个防火墙 4.关闭第二 ...
- 20140914 1到N自然数排序
1.关于一道1到N自然数排序的华为面试题 http://blog.csdn.net/hongyuan19/article/details/1887656 为什么想进入华为 你对华为了解多少? 华为给我 ...
- JS轻松实现单击文本框弹出选择日期
我的开发工具是vs2005,你们可选择自己合适的开发工具 首先创建个文本框<input id="txFDate" name="txFDate" type= ...
- QT的一些小知识
记录一下前段时间工作中用到的东西,包括开发工具和一些简单的技巧吧.也许对于大家来说耳熟能详了. 最开始学习QT记得是在Ubuntu12.04下用apt命令行的方式安装了QT4.8.4以及QT Crea ...
- JS提示信息来检测相应id的标签
2015-07~2015-08 (其中$为document.getElementById()) 使用span提示信息来检测相应id的标签,没有返回值 infoTips("LRYH" ...
- 实现一个EventEmitter类,这个类包含以下方法: on/ once/fire/off
实现一个EventEmitter类,这个类包含以下方法: on(监听事件,该事件可以被触发多次)- once(也是监听事件,但只能被触发一次)- fire(触发指定的事件)- off(移除指定事件的某 ...