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.算法概念. 二分查找算法也称为折半搜索 ...
随机推荐
- python16_day20【Django_继续抽屉项目】
一.djangoAdmin和表结构 1.项目名称 python manage startapp web # 前端页面 python manage startapp repository # 只是数 ...
- 跨域问题-nginx代理
有时候我们跨域是借助了浏览器对 Access-Control-Allow-Origin 的支持.但有些浏览器是不支持的,所以这并非是最佳方案现在我们来利用nginx 通过反向代理 满足浏览器的同源策略 ...
- javascript使用百度地图api和html5特性获取浏览器位置
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>&l ...
- NGUI混合FingerGesture《卷一》 统一坐标
问题背景 使用FingerGesture 获取触碰点2D坐标, 将该2D坐标赋值给NGUI元素,发现位置出现偏差. 排查思路 1:NGUI的 (0,0,0)默认位置是在屏幕正中心.而FingerGes ...
- (转载)sql注入实战 mysql篇
出现的关键名词有: UNION SELECT load_file hex 为了方便说明我们先创建两个表:hehe和heihei,很明显它们一个拥有2列属性,一个拥有3列属性 ======== ...
- 关于Socket和ServerSocket类详解
Socket类 套接字是网络连接的一个端点.套接字使得一个应用可以从网络中读取和写入数据.放在两个不同计算机上的两个应用可以通过连接发送和接受字节流.为了从你的应用发送一条信息到另一个应用,你需要知道 ...
- C++通过HTTP请求Get或Post方式请求Json数据(转)
原文网址:https://www.cnblogs.com/shike8080/articles/6549339.html #pragma once#include <iostream>#i ...
- Centos下Nginx配置WEB访问日志并结合shell脚本定时切割
在一个成熟的WEB系统里,没有日志管理是不可以的,有了日志,可以帮助你得到用户地域来源.跳转来源.使用终端.某个URL访问量等相关信息:通过错误日志,你可以得到系统某个服务或server的性能瓶颈等. ...
- Python3.x:遍历select下拉框获取value值
Python3.x:遍历select下拉框获取value值 Select提供了三种选择方法: # 通过选项的顺序,第一个为 0 select_by_index(index) # 通过value属性 s ...
- SublimeText2 编辑器使用小结
用SublimeText 2进行前端开发也有一段时间了,所谓“工欲善其事必先利其器”,前几日对照着网易课程又重新温习总结了一下有关SublimeText编辑器的使用方式,有所收获,在此进行一次小小的总 ...