POJ2104 (平方分割)二分查找理解。
题意:任意区间求第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 = -, r = n;
while(l < r-)
{
int mid = (l+r)/;
if(check(mid))
l = mid;
else
r = 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 1000 using 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 = ; 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 = ; i < MAXN/B; i ++)
sort(bucket[i].begin(), bucket[i].end());
while(m --)
{
scanf("%d%d%d", &x, &y, &k);
x--, y;
int l = -, r = n-; //(l, r]
while(l < r-)
{
int mid = (l+r)/;
int tx = x, ty = y;
int cnt = ;
for( ; tx < ty && tx%B != ; tx ++)
if(a[tx] <= q[mid]) cnt ++;
for( ; tx < ty && ty%B != ; ty --)
if(a[ty-] <= 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;
else
l = mid;
}
if(r < )
printf("-1");
else
printf("%d\n", q[r]);
}
return ;
}
例如本题若换成[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 1000 using 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 = ; 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 = ; i < MAXN/B; i ++)
sort(bucket[i].begin(), bucket[i].end());
while(m --)
{
scanf("%d%d%d", &x, &y, &k);
x--, y;
int l = , r = n; //[l, r)
while(l < r-)
{
int mid = (l+r)/;
int tx = x, ty = y;
int cnt = ;
for( ; tx < ty && tx%B != ; tx ++)
if(a[tx] < q[mid]) cnt ++;
for( ; tx < ty && ty%B != ; ty --)
if(a[ty-] < 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;
else
r = mid;
}
printf("%d\n", q[l]);
}
return ;
}
POJ2104 (平方分割)二分查找理解。的更多相关文章
- 静态区间第k大(分桶法和平方分割)
POJ 2104为例 思想: <挑战程序设计竞赛>中介绍的方法. 分桶法:把一排物品或者平面分成桶,每个桶分别维护自己内部的信息,已达到高效计算的目的. 设一共有n个数,每b个分到一个桶里 ...
- POJ2104 K-th Number 静态区间第k最值 平方分割
干掉这道题的那一刻,我只想说:我终于**的AC了!!! 最终内存1344K,耗时10282ms,比起归并树.划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙ 但至少,从最初的无数次TLE到最终的AC ...
- 二分查找——没有想象中的容易(详解各种变式,超深度理解,c++)
int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 注意 while(le ...
- 从一个NOI题目再学习二分查找。
二分法的基本思路是对一个有序序列(递增递减都可以)查找时,测试一个中间下标处的值,若值比期待值小,则在更大的一侧进行查找(反之亦然),查找时再次二分.这比顺序访问要少很多访问量,效率很高. 设:low ...
- StringBuffer、StringBuilder、冒泡与选择排序、二分查找、基本数据类型包装类_DAY13
1:数组的高级操作(预习) (1)数组:存储同一种数据类型的多个元素的容器. (2)特点:每个元素都有从0开始的编号,方便我们获取.专业名称:索引. (3)数组操作: A:遍历 public stat ...
- 实现 sqrt(x):二分查找法和牛顿法
最近忙里偷闲,每天刷一道 LeetCode 的简单题保持手感,发现简单题虽然很容易 AC,但若去了解其所有的解法,也可学习到不少新的知识点,扩展知识的广度. 创作本文的思路来源于:LeetCode P ...
- js基本算法:冒泡排序,二分查找
知识扩充: 时间复杂度:算法的时间复杂度是一个函数,描述了算法的运行时间.时间复杂度越低,效率越高. 自我理解:一个算法,运行了几次时间复杂度就为多少,如运行了n次,则时间复杂度为O(n). 1.冒泡 ...
- 用c语言编写二分查找法
二分法的适用范围为有序数列,这方面很有局限性. #include<stdio.h> //二分查找法 void binary_search(int a[],int start,int mid ...
- 二分查找算法java实现
今天看了一下JDK里面的二分法是实现,觉得有点小问题.二分法的实现有多种今天就给大家分享两种.一种是递归方式的,一种是非递归方式的.先来看看一些基础的东西. 1.算法概念. 二分查找算法也称为折半搜索 ...
随机推荐
- 工作笔记-javascript-网络层封装
/** * @Author Mona * @Date 2016-12-08 * @description 网络层封装 */ /** * 封装基本请求方式 */ window.BaseRequest = ...
- yii2 商品上下架
视图层 <td><?php if($value['is_on_sale'] == 1) {?><img src="../web/images/yes.gif&q ...
- 360急速浏览器JS的调试
1.代码中添加debugger关键字 2.360急速浏览器中选择工具--开发人员选项,如下图所示,在sources面板中可以看到正在运行的JS代码,F10可以单步函数执行,在鼠标放在变量上可以跟踪变量 ...
- 机器学习实战python3 决策树ID3
代码及数据:https://github.com/zle1992/MachineLearningInAction 决策树 优点:计算复杂度不高,输出结果易于理解,对中间值的缺失不敏感,可以处理不相关特 ...
- matlab和mathematics最新的FTP地址
https://dio.obspm.fr/interne/logiciels/matlab/ 分享一个地址,非常好的FTP网站.
- cocos2d: fullPathForFilename: No file found at /cc_2x2_white_image. Possible missing file.
程序运行的时候输出这条信息cocos2d: fullPathForFilename: No file found at /cc_2x2_white_image. Possible missing fi ...
- sublime 安装插件报错
sublime 安装插件报错,大部分原因是本地防火墙开启了,关闭本地防火墙
- js 空数组 空对象判断
js 空数组是true还是false 1 2 var arr = new Array(); // 或 var arr = []; 我们知道,初始化后,即使数组arr中没有元素,也是一个object ...
- STM32 CRC32与对应的软件CRC32(转)
源:STM32 CRC32与对应的软件CRC32 简单实现STM32 CRC32使用 使用前记得使能STM32 CRC时钟 //STM32硬件CRC32 byte数据计算,将数据移到最高位,低位补上F ...
- c++第三十一天
p159~p164:switch语句1.例程:统计文本中五个元音字母出现的次数.(利用输入输出重定向测试) $ a <input.txt>output.txt #include <i ...