POJ 2104 K-th Number 平方分割(分桶法)

news2024/11/16 1:55:00

一、题目大意

长度为n(n<=100000)的数组,进行m次查询(m<=5000),每次查询时,输入为 i j k,返回为数组 [i,j] 的分片里第k大数字(1<=i<=j<=n,k<=j-i+1)

二、解题思路

如果采用朴素的方法去计算,针对每次的i 和 j,从 i 到 j 循环把数组的元素放在一个tmp数组里,然后给tmp数组排序,输出tmp[k]的话,在最差情况下,时间复杂性为 O ( m * n * log(n) ),也就是10000000000左右,肯定是行不通的。

于是考虑使用平方分割,按 floor(sqrt(n))为一块,分成根号n块,然后把每一块的数字进行排序,根据查询的 i 和 j,找出 i 和 j 范围内所有的块,然后把 块未覆盖到的左边的和右边范围内放在一个 other数组里,把other数组排序。

这时相当于得到多个有序的块,然后我们需要找到这些块合并在一起后的第k大的,朴素的合并多的话,还是会很慢(合并两个有序数组为一个的操作次数,为其中大的数组的长度),所以考虑二分,可以对数组内所有的元素进行排序。

设一开始输入的数组为dat,那么我们把dat排序后作为sortedDat,然后 L = -1,R=n(二分时候的 l 和 r 是达不到的,都取开区间)当L+1 < R时循环,mid = (L+R)/2,然后我们再循环对这些块来使用二分,找到所有块中小于sortedDat[mid]的数量和cnt,如果cnt<k,则L=mid,否则R=mid,这样的话,最终的临界情况就是,所有块中,小于sortedDat[L]的元素为k-1个,小于sortedDat[L+1]的元素为k个,此时,sortedDat[L]就是当前区间里第k大的数。

考虑下复杂性 O(log(n)*sqrt(n)*log(n)*m),好像是可以的,但实际并不如此。

此时我们需要对算法进行优化,如何优化呢?考虑下比较糟糕的情况,假如n=100000,则我们会分316块,假设涉及的区间包含200块,那么每次二分,循环200次,然后200次循环里还有2分,起始也可能会比较慢,所以我们考虑如何把200个小块合并,假设2个相邻的合并成一个,改成100的话,速度可以快一倍。

于是我们可以在起初分桶的时候,按2 * floor(sqrt(n)) 来分一些大块,然后对这些块也都进行排序,一个大块相当于2个小块。

于是我们执行每次查询时需要进行的操作为:

1、根据区间 i j 找到包含的桶

2、根据找到的桶,来处理不在桶内,而且被 i 和 j 包含的区间,对此区域排序并记录长度。

3、循环包含的桶,如果 两个相邻的小桶可以被一个大桶替换的话,则用这个大桶替换掉小桶,依据此思路,把所有的小桶都用大桶替换。

4、 对sortedDat里面的数进行二分,L = -1,R=n,针对每次的mid,循环里利用二分找到所有涉及的小桶、大桶和其他区域里小于 sortedDat[mid]的数量总和cnt,如果cnt小于k,则L=mid,否则R=mid,循环结束时,输出sortedDat[L]即可

(如果不涉及到任何桶,那直接输出other[k-1]即可,不用走二分这个思路)

(然后利用大桶替换小桶时,可以循环涉及的小桶,如果它不是涉及到的最后一个,且它的下标 i是偶数,则它和它的下一个被一个大桶替换,否则的话这个桶保留,简单的思路就是定义一个变量i=0,设当前区间涉及的小桶数量为bucketLen,保存当前区间相关的桶的数组为bucket,然后 i < bucketLen时候循环,如果i+1小于bucketLen且bucket[i]%2==0,那么就把 i /2记录为当前涉及的大桶 bucketBig[bigLen++]=i/2,然后i +=2,否则就把 bucket[i]加到队列里,最后把不在队列里的小桶都去掉,把队列里的小桶记录下来为替换后涉及到的小桶,然后大桶就是bucketBig里的大桶)

(我针对桶的下标从0开始计算,然后下标 i 的小桶的区间为 [ i * 根号n , (i + 1) * 根号n),下标 i 的大桶的区间为[ 2 *  i * 根号n , (i + 1) * 2 * 根号n),这样的话大桶 i /2就代表小桶 i 和 i + 1,需要i%2==0 )

优化之后,就侥幸过了

三、代码

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int bucket[320][320];
int bucket_1[160][640];
int dat[100009], sortedDat[100009], n, bQue[320], queLen, bQue_1[160], queLen_2, b, otherLen, other[100009];
queue<int> que;
void input()
{
    for (int i = 0; i < n; i++)
    {
        scanf("%d", &dat[i]);
        sortedDat[i] = dat[i];
    }
    sort(sortedDat, sortedDat + n);
}
void bucketMethod()
{
    b = 1;
    while (b * b <= n)
    {
        b++;
    }
    b--;
    for (int i = 0; ((i + 1) * b) <= n; i++)
    {
        for (int j = 0; j < b; j++)
        {
            bucket[i][j] = dat[j + (i * b)];
        }
        sort(bucket[i], bucket[i] + b);
    }
    for (int i = 0; ((i + 1) * 2 * b) <= n; i++)
    {
        for (int j = 0; j < (2 * b); j++)
        {
            bucket_1[i][j] = dat[j + (i * b * 2)];
        }
        sort(bucket_1[i], bucket_1[i] + (2 * b));
    }
}
void findBucket(int L, int R)
{
    queLen = 0;
    for (int i = 0; ((i + 1) * b) <= n; i++)
    {
        if ((i * b) >= L && ((i + 1) * b) <= R)
        {
            bQue[queLen++] = i;
        }
    }
}
void handleOther(int L, int R)
{
    otherLen = 0;
    if (queLen == 0)
    {
        for (int i = L; i < R; i++)
        {
            other[otherLen++] = dat[i];
        }
    }
    else
    {
        for (int i = L; i < (bQue[0] * b); i++)
        {
            other[otherLen++] = dat[i];
        }
        for (int i = ((bQue[queLen - 1] + 1) * b); i < R; i++)
        {
            other[otherLen++] = dat[i];
        }
    }
    if (otherLen > 0)
    {
        sort(other, other + otherLen);
    }
}
void findBucketPlus()
{
    queLen_2 = 0;
    if (queLen == 0)
    {
        return;
    }
    while (!que.empty())
    {
        que.pop();
    }
    int i = 0;
    while (i < queLen)
    {
        if ((i + 1) < queLen && (bQue[i] % 2 == 0))
        {
            bQue_1[queLen_2++] = bQue[i] / 2;
            i += 2;
        }
        else
        {
            que.push(bQue[i]);
            i++;
        }
    }
    if (queLen_2 != 0)
    {
        queLen = 0;
        while (!que.empty())
        {
            int _front = que.front();
            que.pop();
            bQue[queLen++] = _front;
        }
    }
}
int binarySearch(int *arr, int len, int num)
{
    int l = -1, r = len;
    while (l + 1 < r)
    {
        int mid = (l + r) / 2;
        if (arr[mid] < num)
        {
            l = mid;
        }
        else
        {
            r = mid;
        }
    }
    return (l + 1);
}
void solve(int k)
{
    if (queLen == 0 && queLen_2 == 0)
    {
        printf("%d\n", other[k - 1]);
        return;
    }
    int l = -1, r = n;
    while (l + 1 < r)
    {
        int mid = (l + r) / 2;
        int cnt = 0;
        for (int i = 0; i < queLen; i++)
        {
            cnt = cnt + binarySearch(bucket[bQue[i]], b, sortedDat[mid]);
        }
        for (int i = 0; i < queLen_2; i++)
        {
            cnt = cnt + binarySearch(bucket_1[bQue_1[i]], 2 * b, sortedDat[mid]);
        }
        if (otherLen > 0)
        {
            cnt = cnt + binarySearch(other, otherLen, sortedDat[mid]);
        }
        if (cnt < k)
        {
            l = mid;
        }
        else
        {
            r = mid;
        }
    }
    printf("%d\n", sortedDat[l]);
}
int main()
{
    int m, i, j, k;
    while (~scanf("%d%d", &n, &m))
    {
        input();
        bucketMethod();
        while (m--)
        {
            scanf("%d%d%d", &i, &j, &k);
            findBucket(i - 1, j);
            handleOther(i - 1, j);
            findBucketPlus();
            solve(k);
        }
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1063824.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Java的校园自助洗衣系统设计与实现(源码+lw+ppt+部署文档+视频讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

python机器学习之梯度下降法

系列文章目录 第一章 Python 机器学习入门之线性回归 第一章 Python 机器学习入门之梯度下降法 梯度下降法 系列文章目录前言一、梯度下降法1.梯度下降法简介2.基本原理 梯度下降函数效果展示 前言 上一篇文章里面说到了用梯度下降法来对最小化代价函数和模型参数进行求解&am…

计算机网络八股

1、请你说说TCP和UDP的区别 TCP提供面向连接的可靠传输&#xff0c;UDP提供面向无连接的不可靠传输。UDP在很多实时性要求高的场景有很好的表现&#xff0c;而TCP在要求数据准确、对速度没有硬件要求的场景有很好的表现。TCP和UDP都是传输层协议&#xff0c;都是为应用层程序服…

八、【快速选择工具组】

文章目录 对象选择工具快速选择工具魔棒工具 对象选择工具 当我们选择对象选择工具时&#xff0c;需要先注意上边有一个循环的圆&#xff0c;它会进行内容识别&#xff0c;当识别完成会停止旋转。这个时候我们按住n键&#xff0c;或者将鼠标放上对应的图形时会出现选中的颜色。…

多实例学习MIL(easy / hard)

多示例学习&#xff08;Multiple Instance Learning&#xff09; - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/377220948 多示例学习 和弱监督&#xff08;weakly supervised&#xff09;有一定的关系&#xff0c;弱监督weakly supervised有三个含义&#xff08;或者说三…

ethercat EOE arp

1 网口设置 电脑地址位169.254.254.3 2 从站地址 3 PING 正常 异常 4 抓包

【方法】如何取消ZIP压缩包的密码?

我们知道&#xff0c;在压缩ZIP文件的时候&#xff0c;可以设置“打开密码”来保护压缩包&#xff0c;那后续不需要保护了&#xff0c;不想每次打开压缩包都输一次密码&#xff0c;要如何取消密码呢&#xff1f; 比较常用的方法是先把ZIP压缩包解压后&#xff0c;再压缩成没有…

铝合金分类及相关总结

1 铝合金常识 铝合金是工业中应用最广泛的一类有色金属结构材料&#xff0c;在航空、航天、汽车、机械制造、船舶及化学工业中已大量应用。对于常用的铝合金&#xff0c;我们通常根据其铝及其他元素的含量&#xff0c;将其分为两大类&#xff0c;分别是纯铝和铝合金。对这两大类…

网络安全行业真的内卷了吗?网络安全就业就业必看

前言 有一个特别流行的词语叫做“内卷”&#xff1a; 城市内卷太严重了&#xff0c;年轻人不好找工作&#xff1b;教育内卷&#xff1b;考研内卷&#xff1b;当然还有计算机行业内卷…… 这里的内卷当然不是这个词原本的意思&#xff0c;而是“过剩”“饱和”的替代词。 按照…

JMeter接口自动化测试(数据驱动)

之前我们的用例数据都是配置在HTTP请求中&#xff0c;每次需要增加&#xff0c;修改用例都需要打开JMeter重新编辑&#xff0c;当用例越来越多的时候&#xff0c;用例维护起来就越来越麻烦&#xff0c;有没有好的方法来解决这种情况呢&#xff1f;我们可以将用例的数据存放在cs…

Effective Modern C++ 第七章 并发API 2

目录 条款37&#xff1a;使std::thread型别对象在所有路径皆不可联结 要点速记&#xff1a; 条款38&#xff1a;对变化多端的线程句柄析构函数行为保持关注 要点速记&#xff1a; 参考&#xff1a;EffectiveModernCppChinese/src/7.TheConcurrencyAPI/item37.md at master …

【java爬虫】使用vue+element-plus编写一个简单的管理页面

前言 前面我们已经将某宝联盟的数据获取下来了&#xff0c;并且编写了一个接口将数据返回&#xff0c;现在我们需要使用vueelement-plus编写一个简单的管理页面进行数据展示&#xff0c;由于第一次使用vue编写前端项目&#xff0c;所以只是编写了一个非常简单的页面。 项目结…

3263页学习资料,一本在手,python不愁!

Python3.11已经发布&#xff0c;新的版本速度提升2倍&#xff0c;以弥补与其他编程语言在速度上的缺陷。可以预见Python语言在未来的应用范围会越来越广。 python学习方向建议&#xff1a; 如果你是本科及以下学历&#xff0c;建议你学习以下两个方向 爬虫。简单的爬虫库&am…

异步电机直接转矩控制学习(两电平12扇区)

导读&#xff1a;传统的直接转矩控制方法6扇区电压矢量选择会导致磁链控制不对称、转矩脉动大等问题&#xff0c;本期介绍一种把扇区细分为12扇区的新型三相异步电机直接转矩控制方法&#xff0c;仿真结果证明磁链轨迹、转速及转矩脉动明显变小&#xff0c;异步电机三相定子电流…

Mac上protobuf环境构建-java

参考文献 getting-started 官网pb java介绍 maven protobuf插件 简单入门1 简单入门2 1. protoc编译器下载安装 https://github.com/protocolbuffers/protobuf/releases?page10 放入.zshrc中配置环境变量  ~/IdeaProjects/test2/ protoc --version libprotoc 3.12.1  …

Reset信号如何同步?

首先来复习一个更加基础的概念&#xff1a;同步reset和异步reset。 同步reset&#xff08;synchronous reset&#xff09;是说&#xff0c;当reset信号为active的时候&#xff0c;寄存器在下一个时钟沿到来后被复位&#xff0c;时钟沿到来之前寄存器还是保持其之前的值。 异步…

【计算机组成 课程笔记】7.1 存储层次结构概况

课程链接&#xff1a; 计算机组成_北京大学_中国大学MOOC(慕课) 7 - 1 - 701-存储层次结构概况&#xff08;15-14--&#xff09;_哔哩哔哩_bilibili 这是我们已经非常熟悉的冯诺依曼计算机结构&#xff0c; 其中和存储功能相关的部件有&#xff1a;存储器和外部记录介质肯定具有…

WEB各类常用测试工具

一、单元测试/测试运行器 1、Jest 知名的 Java 单元测试工具&#xff0c;由 Facebook 开源&#xff0c;开箱即用。它在最基础层面被设计用于快速、简单地编写地道的 Java 测试&#xff0c;能自动模拟 require() 返回的 CommonJS 模块&#xff0c;并提供了包括内置的测试环境 …

Stm32_标准库_6_八种输入出模式

上拉输入与下拉输入 上拉输入&#xff1a;电平默认为高电平&#xff0c;只有当外部输入为低电平时&#xff0c;此IO口电平才会被拉低&#xff0c;经过触发器&#xff0c;再到寄存器&#xff0c;最后传入CPU GPIO_Mode_IPU&#xff1b;下拉输入&#xff1a;电平默认为低电平&am…

4.MySql安装配置(更新版)

MySql安装配置 无论计算机是否有安装其他mysql&#xff0c;都不要卸载。 只要确定大版本是8即可&#xff0c;8.0.33 8.0.34 差别不大即可。 MySql下载安装适合电脑配置属性有关&#xff0c;一次性安装成功当然是非常好的&#xff0c;因为卸载步骤是非常麻烦的 如果第一次安装…