题意:任意区间求第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 (平方分割)二分查找理解。的更多相关文章

  1. 静态区间第k大(分桶法和平方分割)

    POJ 2104为例 思想: <挑战程序设计竞赛>中介绍的方法. 分桶法:把一排物品或者平面分成桶,每个桶分别维护自己内部的信息,已达到高效计算的目的. 设一共有n个数,每b个分到一个桶里 ...

  2. POJ2104 K-th Number 静态区间第k最值 平方分割

    干掉这道题的那一刻,我只想说:我终于**的AC了!!! 最终内存1344K,耗时10282ms,比起归并树.划分树以及其他各种黑科技,这个成绩并不算光彩⊙﹏⊙ 但至少,从最初的无数次TLE到最终的AC ...

  3. 二分查找——没有想象中的容易(详解各种变式,超深度理解,c++)

    int binarySearch(int[] nums, int target) { int left = 0; int right = nums.length - 1; // 注意 while(le ...

  4. 从一个NOI题目再学习二分查找。

    二分法的基本思路是对一个有序序列(递增递减都可以)查找时,测试一个中间下标处的值,若值比期待值小,则在更大的一侧进行查找(反之亦然),查找时再次二分.这比顺序访问要少很多访问量,效率很高. 设:low ...

  5. StringBuffer、StringBuilder、冒泡与选择排序、二分查找、基本数据类型包装类_DAY13

    1:数组的高级操作(预习) (1)数组:存储同一种数据类型的多个元素的容器. (2)特点:每个元素都有从0开始的编号,方便我们获取.专业名称:索引. (3)数组操作: A:遍历 public stat ...

  6. 实现 sqrt(x):二分查找法和牛顿法

    最近忙里偷闲,每天刷一道 LeetCode 的简单题保持手感,发现简单题虽然很容易 AC,但若去了解其所有的解法,也可学习到不少新的知识点,扩展知识的广度. 创作本文的思路来源于:LeetCode P ...

  7. js基本算法:冒泡排序,二分查找

    知识扩充: 时间复杂度:算法的时间复杂度是一个函数,描述了算法的运行时间.时间复杂度越低,效率越高. 自我理解:一个算法,运行了几次时间复杂度就为多少,如运行了n次,则时间复杂度为O(n). 1.冒泡 ...

  8. 用c语言编写二分查找法

    二分法的适用范围为有序数列,这方面很有局限性. #include<stdio.h> //二分查找法 void binary_search(int a[],int start,int mid ...

  9. 二分查找算法java实现

    今天看了一下JDK里面的二分法是实现,觉得有点小问题.二分法的实现有多种今天就给大家分享两种.一种是递归方式的,一种是非递归方式的.先来看看一些基础的东西. 1.算法概念. 二分查找算法也称为折半搜索 ...

随机推荐

  1. Leetcode 235

    思路1:对于一棵二叉排序树 1.如果当前节点的值小于p,q的值,那么LCA一定在root的右边: 2.如果当前节点的值大于p,q的值,那么LCA一定在root的左边: 3.如果当前节点的值在p,q的值 ...

  2. HackerRank - greedy-florist 【贪心】

    HackerRank - greedy-florist [贪心] 题意 有N个人 要去买K朵花.老板为了最大化新顾客的数量.就压榨回头客.每一朵花都有一个基本价格.一个顾客买下这朵花的价格是他来这里买 ...

  3. win 7 64 安装 MondgoDB 3.4

    https://jingyan.baidu.com/article/f3e34a12ac10cef5eb653583.html mongod --dbpath "D:\Program Fil ...

  4. SpringBoot入门学习(二)

    第一讲我们已经讲解了入门Demo,这一讲我们主要讲解包含以下内容 项目内一些属性配置 自定义属性配置 ConfigurationProperties配置 (1)第一个工程创建的时候会自动在工程下创建a ...

  5. HDFS数据块

    磁盘也是由数据块组成的,一般默认大小是512字节,构建磁盘之上的文件系统一般是磁盘块的整数倍.         HDFS也是采用块管理的,但是比较大,在Hadoop1.x中默认大小是64M,Hadoo ...

  6. 【英语学习】How do I stop overthinking at night?

    2017-04-03 If you were to say to the grown-ups: "I saw a beautiful house made of rosy brick, wi ...

  7. Tomcat的工作模式和运行模式

    (1)工作模式 Tomcat作为servlet容器,有三种工作模式: 1.独立的servlet容器,servlet容器是web服务器的一部分: 2.进程内的servlet容器,servlet容器是作为 ...

  8. [BZOJ5102]Prawnicy

    Description 定义一个区间(l,r)的长度为r-l,空区间的长度为0. 给定数轴上n个区间,请选择其中恰好k个区间,使得交集的长度最大. Input 第一行包含两个正整数n,k(1<= ...

  9. ethtool命令详解

    命令描述: ethtool 是用于查询及设置网卡参数的命令. 使用概要:ethtool ethx       //查询ethx网口基本设置,其中 x 是对应网卡的编号,如eth0.eth1等等etht ...

  10. 在服务器 部署 asp.net core 报502.5的错

    HTTP Error 502.5 - Process Failure 如果 IIS 该安装的都装好了的话,那就需要安装一个.net core sdk,链接如下: https://www.microso ...