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)或 ...
随机推荐
- redis 4.x及以上的未授权访问
00x01 环境搭建 选择在kali中复现 选择了redis5.0.5版本 1.下载并安装: $ wget http://download.redis.io/releases/redis-5.0.5. ...
- youhua
- Raspbain系统无屏幕无网线通过ssh远程连接树莓派设置wifi步骤
应该是最简单的步骤了,只需通过电脑.路由器.树莓派在同一个局域网即可,它们之间都是无线连接 1.首先通过路由器连接树莓派,查看树莓派的地址 然后我们依旧可以用网线,以及WIFI,连接树莓派,第一次连接 ...
- Docker 镜像仓库为什么要分库分权限?
先说一个事故案例: 场景:某大型互联网电商公司,使用一个镜像仓库管理所有Docker镜像.开发者打出的镜像上传到唯一的镜像库,测试通过后,运维环境的 Kubernetes 直接从这个库里拉取镜像,所有 ...
- ipa文件信息检查工具
项目地址:https://github.com/ryjwinner/softwares/raw/master/iOS-checkIPA.jar 项目简介: 针对近期大量iOS app需要签名,但多家签 ...
- 用Java在excel单元格中设置超链接
(一)问题引入 有时候我们在导入数据到excel中时可能要给某个文件或图片设置超链接,例如链接到外网或者是本地的某个目录.我们可以通过Java代码来实现,借助POI库. (二)解决方案 下面直接给出参 ...
- C++-HDU3400-Line belt[三分]
将军饮马问题的升级版 二维平面中要从A到D,给出两条线段AB,CD,分别在线段AB,CD,以及空白处的速度为P,Q,R 求最少用时 由于最优位置满足“凸性”,且两条线段可以等价,所以可以采取三分答案迭 ...
- 机器学习作业(四)神经网络参数的拟合——Python(numpy)实现
题目下载[传送门] 题目简述:识别图片中的数字,训练该模型,求参数θ. 出现了一个问题:虽然训练的模型能够有很好的预测准确率,但是使用minimize函数时候始终无法成功,无论设计的迭代次数有多大,如 ...
- 如何在macOS下安装geoserver
macOS 下的编译包 如果是使用安装文件,请查看官网文档,如果想要部署在已有的tomcat服务下,请查看网页压缩包章节. Web archive. An alternate way of insta ...
- DataGridView 调整列顺序为设计的顺序
设置: dataGridView1.AutoGenerateColumns = false;