hdu3486Interviewe(二分是错的)(ST算法RMQ + 判定上下界枚举)
题目大意是找最小的m使得前m段中每一段的最大值相加严格大于k,每一段长度为[n/m](n/m向下取整,多余的后半部分部分n-m*[n/m]不要)
先给一段我一开始的思路,和网上许多题解思路一样,但其实是有错误的。二分答案+RMQ (RMQ部分也可以用线段树)
#include <bits/stdc++.h>
using namespace std; const int maxn = 2e5 + ;
const int inf = 0x3f3f3f3f;
int f[maxn][];
int n, k, m, v[maxn];
int mx, mi, tot;
inline int max( int a,int b ){
return a>b ? a:b;
} inline int min( int a, int b ){
return a<b ? a:b;
} inline void ST_make(){
for( int i=; i<=n; i++ )
f[i][] = v[i];
for( int j=; (<<j)<=n; j++ )
for( int i=; i<=n; i++ )
f[i][j] = max( f[i][j-], f[i+(<<(j-))][j-] );
} inline int ST_query( int l, int r ){
int k = log(r-l+)/log();
return max( f[l][k], f[r-(<<k)+][k]);
} int main(){
while( ~scanf("%d%d", &n, &k) ){
if( n< && k< ) break;
memset( f, , sizeof(f) );
mx = -inf; mi = inf;
tot = ;
for( int i=; i<=n; i++ ){
scanf("%d", &v[i]);
tot += v[i];
mx = max( v[i], mx );
mi = min( v[i], mi );
}
if( mx>k ) {puts("1\n"); continue;}
else if( tot<=k ) {puts("-1\n"); continue;}
ST_make();
mx = mx ? mx:;
mi = mi ? mi:;
int l = k/mx, r = min( n, k/mi+ ), sum; //判断上下界,节省时间
while( l<r ){
sum = ;
int mid = l+r>>; //这个地方不能直接用m = l+r>>1
int t = n/mid;
int tmp = ;
int d = t*mid;
while( tmp<d){
sum += ST_query( tmp, tmp+t- );
tmp += t;
}
if( sum>k ){ //符合条件再令m = mid;
r = mid;
m = mid;
}
else l = mid+;
}
printf("%d\n", m);
} return ;
}
思路都写好了,然鹅是错的。。。
给一份Discuss里dalao给的卡二分的数据
#include <bits/stdc++.h>
using namespace std; const int maxn = 2e5 + ;
const int inf = 0x3f3f3f3f;
int f[maxn][];
int n, k, m, v[maxn];
int mx, mi, tot;
inline int max( int a,int b ){
return a>b ? a:b;
} inline int min( int a, int b ){
return a<b ? a:b;
} inline void ST_make(){
for( int i=; i<=n; i++ )
f[i][] = v[i];
int t = log(n)/log()+;
for( int j=; j<t; j++ )
for( int i=; i+(<<j)-<=n; i++ )
f[i][j] = max( f[i][j-], f[i+(<<(j-))][j-] );
} inline int ST_query( int l, int r ){
int k = log(r-l+)/log();
return max( f[l][k], f[r-(<<k)+][k]);
} int main(){
while( ~scanf("%d%d", &n, &k) ){
if( n< && k< ) break;
mx = -inf; mi = inf;
tot = ;
for( int i=; i<=n; i++ ){
scanf("%d", &v[i]);
tot += v[i];
mx = max( v[i], mx );
mi = min( v[i], mi );
}
if( tot<=k ){
printf("-1\n");
continue ;
}
ST_make();
mx = mx ? mx:;
mi = mi ? mi:;
int l = k/mx, r = (k/mi+, n); //判定上下界,节省时间(好像判了上界r还慢了。。)
if(l==) l = ;
bool ok = ;
for( m=l; m<=r; m++ ){
int sum = ;
int t = n/m;
int d = t*m;
for( int i=; i<=d; i+=t ) //这个地方要等于号,可举例n = m时 若i<d为判定条件则不能进行,卡了一年
sum += ST_query( i, i+t- );
if( sum>k ){
ok = ;
break;
}
}
if(ok) printf("%d\n", m);
else printf("-1\n");
}
return ;
}
hdu3486Interviewe(二分是错的)(ST算法RMQ + 判定上下界枚举)的更多相关文章
- 【37.48%】【hdu 2587】How far away ?(3篇文章,3种做法,LCA之ST算法(RMQ))
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...
- 【原创】RMQ - ST算法详解
ST算法: ID数组下标: 1 2 3 4 5 6 7 8 9 ID数组元素: 5 7 3 1 4 8 2 9 8 1.ST算法作 ...
- RMQ问题之ST算法
RMQ问题之ST算法 RMQ(Range Minimum/Maximum Query)问题,即区间最值问题.给你n个数,a1 , a2 , a3 , ... ,an,求出区间 [ l , r ]的最大 ...
- HDU 5289 Assignment (ST算法区间最值+二分)
题目链接:pid=5289">http://acm.hdu.edu.cn/showproblem.php?pid=5289 题面: Assignment Time Limit: 400 ...
- HDU 5443 The Water Problem (ST算法)
题目链接:HDU 5443 Problem Description In Land waterless, water is a very limited resource. People always ...
- CodeForces 359D (数论+二分+ST算法)
题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319 题目大意:给定一个序列,要求确定一个子序列,①使得该子序 ...
- 求解区间最值 - RMQ - ST 算法介绍
解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...
- RMQ之ST算法模板
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; ; ],M ...
- RMQ问题(线段树+ST算法)
转载自:http://kmplayer.iteye.com/blog/575725 RMQ (Range Minimum/Maximum Query)问题是指:对于长度为n的数列A,回答若干询问RMQ ...
随机推荐
- suanec-rotatelogs
简介 一个简单的日志滚动器 业界已有大量优秀的日志滚动工具来限制日志大小 本工具只是仿制了Apache httpd中的rotatelogs 不同的是,工作模式参考了yarn namenode日志的管理 ...
- vue实现视频播放
用的vue组件是vue-video-player,可以去百度下怎么引入到项目中: 因为这个组件是基于H5video实现的,视频格式有所限制,而且MP4不是H264的也不行.转码可以看下我上篇博客,地址 ...
- 19 SpringMVC 拦截器
1. 拦截器的概述(1)SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术.(2)可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链 中的 ...
- Kubernetes exec API串接分析
本篇将说明Kubernetes exec API的运作方式,并以简单范例进行开发在前后端上.虽然Kubernetes提供了不同资源的RESTful API来进行CRUD操作,但是部分API并非单纯的回 ...
- c++ pipe实现父子进程通信
1.父子进程通信pipe编程流程 -创建管道 -设置进程的输出到管道 -创建进程 -关闭管道写句柄 -读管道读句柄,把数据读到一个buffer里 2.注意事项 -读管道数据的时候,一定要关闭写句柄: ...
- day02——while、字符串格式化、运算符、编码初识
day02 while--关键字(死循环) 格式:while 条件: 循环体 print(1) while True: print("痒") print("鸡你太美& ...
- Django框架(十三)——Auth模块
Auth模块 一.什么是auth模块 Auth模块是Django自带的用户认证模块 Auth模块是Django自带的用户认证模块,可以实现包括用户注册.用户登录.用户认证.注销.修改密码等功能.默认使 ...
- stvd使用中的一些问题
1.stm8_interrupt_vector.c 会莫名其妙的自动出现,而且都是在项目目录下.进行如下操作 2.stvd编译时遇到no default placement for segment . ...
- postgresql学习之安装篇
---恢复内容开始--- 安装方法: 1.可以使用操作系统自带的安装源 2.可以使用官网下载的源码进行安装 3.可以使用编译好的包入.run格式的安装包安装(本文使用的是这种安装方法,下载地址http ...
- Docker 封装java镜像
一.概述 目前java采用的框架是Spring,服务器直接通过 java -jar xxx.jar 就可以启动服务了. 二.jdk镜像 在docker中跑java应用,需要有jdk环境支持才行. 获取 ...