当前位置: 首页 > news >正文

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 = -1, r = n;
while(l < r-1)
{
    int mid = (l+r)/2;
    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 = 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;
            else
                l = mid;
        }
        if(r < 0)
            printf("-1");
        else
            printf("%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 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 = 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;
            else
                r = mid;
        }
        printf("%d\n", q[l]);
    }
    return 0;
}
View Code

 

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

相关文章:

  • 常用的SQL跟踪事件类
  • Ioc与DI
  • PHP开发工程师面试笔试
  • oracle jdk 1.6 download link
  • MySQL重命名数据表
  • oracle数据库的随堂笔记(四)-定义并使用变量
  • nginx和apache服务器下配置数据库信息
  • PostgreSQL的分区表建立
  • python的tab自动补全
  • 使用 NuGet 更新套件時將 jQuery 升級到 2.0.2 應該如何降級
  • jquery radio取值,checkbox取值,select取值,radio选中,checkbox选中,select选中,及其相关...
  • 微软职位内部推荐-SW Engineer II for Embedded System
  • JS模块化
  • jQuery事件绑定 bind、 live、delegate和on的区别
  • 注册表检测 ms14-058 CVE-2014-4113
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 2017 前端面试准备 - 收藏集 - 掘金
  • android图片蒙层
  • C语言笔记(第一章:C语言编程)
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • HTTP--网络协议分层,http历史(二)
  • iOS小技巧之UIImagePickerController实现头像选择
  • Java方法详解
  • Js基础——数据类型之Null和Undefined
  • js中forEach回调同异步问题
  • LeetCode18.四数之和 JavaScript
  • vue-router的history模式发布配置
  • 简单基于spring的redis配置(单机和集群模式)
  • 前端性能优化——回流与重绘
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 深入 Nginx 之配置篇
  • 探索 JS 中的模块化
  • NLPIR智能语义技术让大数据挖掘更简单
  • ​你们这样子,耽误我的工作进度怎么办?
  • ​什么是bug?bug的源头在哪里?
  • #1015 : KMP算法
  • (1)SpringCloud 整合Python
  • (ZT)出版业改革:该死的死,该生的生
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)springboot掌上博客系统 毕业设计063131
  • (黑马C++)L06 重载与继承
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (四)linux文件内容查看
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • (转)Mysql的优化设置
  • (转)Oracle 9i 数据库设计指引全集(1)
  • .form文件_SSM框架文件上传篇
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET3.5下用Lambda简化跨线程访问窗体控件,避免繁复的delegate,Invoke(转)
  • .net开发时的诡异问题,button的onclick事件无效
  • .NET框架设计—常被忽视的C#设计技巧