题意:任意区间求第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. Xcode控制台命令

    命令 解释 break NUM 在指定的行上设置断点 bt 显示所有的调用栈帧,该命令可用来显示函数的调用顺序 clear 删除设置在特定源文件.特定行上的断点,其用法为:clear FILENAME ...

  2. Python(^^^^^小技巧^^^^^——不定期更新)

    偶然想到的小技巧 ''' 交互中对传入函数的参数的数目进行检测 ''' def func(a,b,c): print(a,b,c) s=input(">>>>:&qu ...

  3. android 自定义View 对话框

    package com.example.dialog5; import android.os.Bundle;import android.app.Activity;import android.app ...

  4. centos运行asp.netcore的正确姿势

    centos安装.netcore2.0 一切都很顺利,console app运行 dotnet run也ok 但是asp.net core app运行 dotnet run 会抛出Warn:“Unab ...

  5. gitHub新项目的上传

    github作为一个开源托管平台,除了有机会学习各位大神的开源项目,还能托管自己写的一些小Demo,作为github新进菜鸟,今天就整理下上传Demo所需的命令和操作步骤,防止我这谜一样的记忆力. 1 ...

  6. 在Ubuntu14.4(32位)中配置I.MX6的QT编译环境

    1,开发工具下载 一,下载VMware Workstation虚拟机 地址:http://1.xp510.com:801/xp2011/VMware10.7z 二,下载Ubuntu 14.04.5 L ...

  7. 【Thinking in Java, 4e】访问权限控制

    [包:库单元] 编译单元的概念. 一个.java文件就是一个编译单元,一个编译单元只能有一个public类,编译单元中的非public类一般是用于为public类提供支持的,这些类在包外不可见. im ...

  8. 20144303石宇森 《Java程序设计》第2周学习总结

    ---恢复内容开始--- 20144303 <Java程序设计>第2周学习总结 教材学习内容总结 一.类型: 1.Java可以区分为基本类型和类类型.类类型也称作参考类型. 2.Java中 ...

  9. 团队项目系列博客 —— 在路上(之wampserver 修改根目录以及配置多站点以及修改端口号)

    团队项目系列博客 -- 在路上(之wampserver 修改根目录以及配置多站点以及修改端口号) 标签(空格分隔): wampserver php 参考:参考文献1.慕课网.知乎.github 一.w ...

  10. LeetCode(476): Number Complement

    Given a positive integer, output its complement number. The complement strategy is to flip the bits ...