题意:任意区间求第k大数

思路:

  预处理:利用平方分割(分桶法)把区间切割成B = sqrt(n)大小的一块块,然后每个各自排序。

  二分第k大数x,接着就需要求[l,r]区间中x的排名,与k比较,将两边端点非完整桶的点进行扫描,最多B次,其余每个桶进行二分查找排名,可利用upper_bound(STL)即可快速实现。

评价:

  二分确实坑爹,不过搞了这一题也算对二分查找理解深入了些。

二分正确做法:

对于[0..n-1)有[0..m]满足性质其余不满足, 则应用[l, r)进行二分查找, 最后l一定是正确的。总是保证l不成立,r成立。

l = -1, r = n;
while(l < r-1)
{int mid = (l+r)/2;if(check(mid))l = mid;elser = mid;
}
cout << l << endl;

而若是[m, n-1]满足性质, 则应用(l, r]进行二分查找, 最后r一定正确,反之即可。

保证(l, r]正确性

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 0x3f3f3f3f
#define MAXN 200005
#define B 1000using namespace std;vector<int> bucket[MAXN/B];
int a[MAXN], q[MAXN], n, m, x, y, k;int main()
{scanf("%d%d", &n, &m);for(int i = 0; i < n; i ++){scanf("%d", &a[i]);q[i] = a[i];bucket[i/B].push_back(a[i]);}sort(q, q+n);for(int i = 0; i < MAXN/B; i ++)sort(bucket[i].begin(), bucket[i].end());while(m --){scanf("%d%d%d", &x, &y, &k);x--, y;int l = -1, r = n-1; //(l, r]while(l < r-1){int mid = (l+r)/2;int tx = x, ty = y;int cnt = 0;for( ; tx < ty && tx%B != 0; tx ++)if(a[tx] <= q[mid]) cnt ++;for( ; tx < ty && ty%B != 0; ty --)if(a[ty-1] <= q[mid]) cnt ++;for(int i = tx/B; i < ty/B; i ++)cnt += upper_bound(bucket[i].begin(), bucket[i].end(), q[mid])-bucket[i].begin();if(k <= cnt)r = mid;elsel = mid;}if(r < 0)printf("-1");elseprintf("%d\n", q[r]);}return 0;
}

View Code

例如本题若换成[l, r)正确性,稍加改动即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 0x3f3f3f3f
#define MAXN 200005
#define B 1000using namespace std;vector<int> bucket[MAXN/B];
int a[MAXN], q[MAXN], n, m, x, y, k;int main()
{scanf("%d%d", &n, &m);for(int i = 0; i < n; i ++){scanf("%d", &a[i]);q[i] = a[i];bucket[i/B].push_back(a[i]);}sort(q, q+n);for(int i = 0; i < MAXN/B; i ++)sort(bucket[i].begin(), bucket[i].end());while(m --){scanf("%d%d%d", &x, &y, &k);x--, y;int l = 0, r = n; //[l, r)while(l < r-1){int mid = (l+r)/2;int tx = x, ty = y;int cnt = 0;for( ; tx < ty && tx%B != 0; tx ++)if(a[tx] < q[mid]) cnt ++;for( ; tx < ty && ty%B != 0; ty --)if(a[ty-1] < q[mid]) cnt ++;for(int i = tx/B; i < ty/B; i ++)cnt += lower_bound(bucket[i].begin(), bucket[i].end(), q[mid])-bucket[i].begin();if(cnt < k)l = mid;elser = mid;}printf("%d\n", q[l]);}return 0;
}

View Code

转载于:https://www.cnblogs.com/Mathics/p/4155655.html

POJ2104 (平方分割)二分查找理解。相关推荐

  1. POJ2104 K-th Number (平方分割 + 二分)

    题目链接:传送门 题意:输入n个数,然后进行m次操作,每次操作输入三个数l,r,k,输出在[l,r]区间第k小的数 解题思路:这道题做法倒是挺多的,平方分割可以做,归并树,划分树,主席树都能做,但是本 ...

  2. 面试前必知必会的二分查找及其变种

    今天给大家带来的是二分查找及其变种的总结,大家一定要看到最后呀,非常非常用心的一篇文章,废话不多说,让导演帮我们把镜头切到袁记菜馆吧! 袁记菜馆内.... 店小二:掌柜的,您进货回来了呀,哟!今天您买 ...

  3. access 查找工龄大于30_面试前必知必会的二分查找及其变种

    作者 | 袁厨 责编 | 张文 头图 | CSDN 下载自视觉中国 来源 | 袁厨的算法小屋(ID:tan45du_me) 今天给大家带来的是二分查找及其变种的总结. 袁记菜馆内. 店小二:掌柜的,您 ...

  4. 【二分查找】有这一篇足够了

    目录 1.二分查找是干啥的 2. 力扣中的一些练习题 2.1 二分查找(两种方法定义 target 是在一个在左闭右闭的区间里,也就是[left, right] ) 2.2 第一个错误的版本 2.3 ...

  5. 浅谈mysql 平衡二叉树理解_浅析二分查找,二叉树,平衡二叉树,B树,B+树

    二分查找 二分查找是最基本的,后面的二叉树,平衡二叉树,B树,B+树都是基于二分查找演变而来的. 二分查找法作为一种常见的查找方法,将原本是线性时间提升到了对数时间范围,大大缩短了搜索时间,但它有一个 ...

  6. 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式...

    序言 本文以经典的二分查找为例,介绍如何使用循环不变式来理解算法并利用循环不变式在原始算法的基础上根据需要产生算法的变体.谨以本文献给在理解算法思路时没有头绪而又不甘心于死记硬背的人. 二分查找究竟有 ...

  7. LeetCode 410. 分割数组的最大值(极小极大化 二分查找 / DP)

    文章目录 1. 题目 2. 解题 2.1 二分查找 2.2 DP 1. 题目 给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组. 设计一个算法使得这 m 个子数组各自和 ...

  8. 你有进一步深入理解二分查找吗?

    作者 | Cooper Song 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 二分查找也叫折半查找(Binary Search),是一种时间复杂度为O(logn),因为它可以每次都将 ...

  9. 二分查找算法代码详细理解

    前言 以前写了好多次的二分查找了,但对于一些细节感觉还是没有领悟道,比如while循环里面是否加上等号,mid是否要加一等等,每次写的时候虽然都过了,但总感觉是稀里糊涂的过的,这次特意来深度理解下二分 ...

最新文章

  1. 跌宕中,特斯拉拿下上海工厂,给蔚来们留下不到两年窗口期
  2. java 集合接口原理_图文剖析java集合框架—Set接口
  3. 并发编程——进程——Process对象的属性和方法
  4. spring定时任务(@Scheduled注解)
  5. Navicat for MySQL工具创建mysql数据库定时器
  6. php正则式去掉问号后所有,正则表达式如何过滤问号
  7. bcscale php,【PHP开发】bcscale timezone charset的设定说明
  8. oracle11 rman全备,Oracle 11g非归档模式下mount状态RMAN究竟能不能进行全备?
  9. 2017年最流行的5个php开发框架视频教程推荐
  10. 使用 TeamCity 实现持续集成(CI)
  11. java快速排列马桶,马桶Java :6.高性能MySQL语句(二)
  12. 去除地址栏带#的问题
  13. lr中错误解决方法(收集)
  14. oracle数据库使用odbc导出到access失败
  15. 实训三:交换机恢复出厂设置以及基本配置
  16. Android ASM插桩
  17. word插入漂亮的代码块
  18. R语言学习记录:sample()函数
  19. 3dmax云渲染哪个平台好用性价比高?
  20. 计算思维(美国CMU周以真教授)

热门文章

  1. 多个数字数组_七个问题帮助初学者深入理解Java数组
  2. qq五笔linux,QQ五笔 - 五笔小字典 QQ绑定很实用
  3. Linux GRUB 引导Win 7 ---- error: invalid EFI file path
  4. 嵌套矩形——DAG上的动态规划
  5. 160 - 8 Andrnalin.1
  6. java uuid静态方法_Java UUID getLeastSignificantBits()方法与示例
  7. scala 函数调用_在Scala中按名称调用函数
  8. 13-Canny边缘检测
  9. Eclipse和Tomcat绑定并且将上传资源到Tomcat上
  10. 20160828_第4周周报