HDU多校第三场 Hdu6606 Distribution of books 线段树优化DP
Hdu6606 Distribution of books
题意
把一段连续的数字分成k段,不能有空段且段和段之间不能有间隔,但是可以舍去一部分后缀数字,求\(min(max((\sum ai ))\)其中\(\sum ai\)为一段的数字和
分析
最小化最大值问题通常我们要想到二分,所以答案的求法我们就解决了,但是二分我们怎么check呢?这个时候一点思路都没有,我们考虑暴力的算法,设dp[i]表示从1--i最多可以分成多少段,怎么转移,什么情况下可以转移呢?
显然\(dp[i]=max(dp[j]+[sum[i]-sum[j]<=x])\)这样就能取到最多段了,但是这个转移的写法是\(O(n^2)\)的暴力算法,显然不满足题目的复杂度,这就到了这个题目的难点了,如何对dp进行优化,对dp进行优化的方式有多种,单调栈、平行四边形、线段树、主席树等。
关于dp优化:https://blog.csdn.net/qq_35649707/article/details/77834685
这里因为取值满足不等式,而不等式所表示的值域就是天然的区间,区间问题肯定非线段树莫属。我们采用线段树优化,使用权值线段树的节点对应离散化后的sum值,从而维护dp的值,由不等\(sum[i]-sum[j]<=x\)我们转化为\(sum[i]-x<=sum[j]\)即只要找第一个满足该不等式的sum,然后在\([j,m]\)中找最大的dp值即可转移,复杂度就优化到了\(O(nlognlogn)=O(nlog^2n)\)
#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
#define pii pair<int,int>
#define mkp make_pair
typedef long long ll;
using namespace std;
const int maxn=2e5+5;
int tr[maxn<<2];
int a[maxn];
ll sum[maxn],v[maxn];
int t,n,k,flag,cnt=0,sz;
void build(int o,int l,int r){
tr[o]=-maxn;
if(l==r)return ;
int mid=l+r>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
}
void update(int o,int l,int r,int p,int v){
if(l==r)tr[o]=max(tr[o],v);
else {
int mid=l+r>>1;
if(mid>=p)update(o<<1,l,mid,p,v);
else update(o<<1|1,mid+1,r,p,v);
tr[o]=max(tr[o<<1],tr[o<<1|1]);
}
}
int query(int o,int l,int r ,int x,int y){
if(x<=l&&y>=r)return tr[o];
int mid=l+r>>1;
int ans=-maxn;
if(mid>=x)ans=max(ans,query(o<<1,l,mid,x,y));
if(mid<y)ans=max(ans,query(o<<1|1,mid+1,r,x,y));
return ans;
}
bool check(ll x){
build(1,1,sz);
for(int i=1;i<=n;i++){
int l=lower_bound(v+1,v+1+sz,sum[i]-x)-v;
int id=lower_bound(v+1,v+1+sz,sum[i])-v;
//cout<<" i "<<i<<" l "<<l<<" id "<<id<<" sum-x "<<sum[i]-x<<endl;
if(l>sz){
if(sum[i]<=x)
update(1,1,sz,id,1);
}
else {
int t=query(1,1,sz,l,sz);
//cout<<i<<" t "<<t<<endl;
if(t==-maxn){
if(sum[i]<=x)
update(1,1,sz,id,1);
}
else
update(1,1,sz,id,t+1);
}
}
//cout<<query(1,1,sz,1,sz)<<endl;
return query(1,1,sz,1,sz)>=k;
}
int main(){
scanf("%d",&t);
while(t--){
cnt=1;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum[i]=sum[i-1]+a[i];
v[cnt++]=(sum[i]);
}
cnt--;
sort(v+1,1+v+cnt);
sz=unique(v+1,v+1+cnt)-v-1;
// for(int i=1;i<=sz;i++)cout<<v[i]<<" ";
// cout<<endl;
//cout<<sz<<endl;
ll l=-1e14;
ll r=-l;
ll ans=1e15;
while(l<=r){
ll mid=l+r>>1;
//cout<<l<<" "<<r<<endl;
if(check(mid)){
ans=min(ans,mid);
r=mid-1;
}
else l=mid+1;
}
printf("%lld\n",ans);
}
return 0;
}
HDU多校第三场 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杭电多校第三场hdu6606 Distribution of books(二分答案+dp+权值线段树)
Distribution of books 题目传送门 解题思路 求最大值的最小值,可以想到用二分答案. 对于二分出的每个mid,要找到是否存在前缀可以份为小于等于mid的k份.先求出这n个数的前缀和 ...
- [2019杭电多校第三场][hdu6609]Find the answer(线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6609 大致题意是求出每个位置i最小需要将几个位置j变为0(j<i),使得$\sum_{j=1}^ ...
- hdu 5316 Magician(2015多校第三场第1题)线段树单点更新+区间合并
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5316 题意:给你n个点,m个操作,每次操作有3个整数t,a,b,t表示操作类型,当t=1时讲a点的值改 ...
- 2019杭电多校第三场hdu6609 Find the answer(线段树)
Find the answer 题目传送门 解题思路 要想变0的个数最少,显然是优先把大的变成0.所以离散化,建立一颗权值线段树,维护区间和与区间元素数量,假设至少减去k才能满足条件,查询大于等于k的 ...
- 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)
题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...
- 2018 HDU多校第三场赛后补题
2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...
- hdu 3698 UVA1490 Let the light guide us 线段树优化DP
题目链接 and 题目大意 hdu3698 但是 hdu的数据比较弱,所以在这luogu提交吧UVA1490 Let the light guide us 有一个\(n*m\)的平原,要求每行选一个点 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
随机推荐
- 【终端使用】常用Linux命令的基本使用
常用Linux命令的基本使用: 命令 对应英文 作用 ls list 查看当前文件夹下的内容 pwd print work directory 查看当前所在的文件夹 cd [目录名] change d ...
- java使用JDBC连接hive(使用beeline与hiveserver2)
首先虚拟机上已经安装好hive. 下面是连接hive需要的操作. 一.配置. 1.查找虚拟机的ip 输入 ifconfig 2.配置文件 (1)配置hadoop目录下的core-site.xml和hd ...
- 两个html页面之间传值
参考网址:https://blog.csdn.net/csdn_ds/article/details/78393564?locationNum=8&fps=1
- Cenos7 学习笔记
一.nmtui nmtui——Text User Interface for controlling NetworkManager,这是一个NetworkManager服务的网卡接口配置工具,能实现在 ...
- java类及实例初始化顺序
1.静态变量.静态代码块初始化顺序级别一致,谁在前,就先初始化谁.从上而下初始化(只在类加载时,初始化一次) 2.非静态变量.非静态代码块初始化顺序级别一致,谁在前,就先初始化谁.从上而下初始化(只要 ...
- 微信小程序自定义顶部导航
注释:自定义导航需要自备相应图片 一.设置自定义顶部导航 Navigation是小程序的顶部导航组件,当页面配置navigationStyle设置为custom的时候可以使用此组件替代原生导航栏. 1 ...
- eclipse如何查看源码
方式一: Source not found The JAR file X:\xxxx\xxxx\xxxx\xx has no source attachment. 没有源附件. You can att ...
- linux - 查看 python 版本
命令 python -V 结果
- JS调用函数的两种方式
<script type="text/javascript"> window.onload = init; //onload 表示页面全部加载完毕后,再调用init() ...
- eclipse下载更新可用的SDK 2018-11-12
懒人方法: mirrors.neusoft.edu.cn:80 操作步骤: 1. Android SDK Manager----Tools----Options-----Http Proxy Serv ...