华南理工大学程序设计竞赛 - A-KNN算法 (二分)

二分距离

期末考试在即,紧张预习数据挖掘的 Capps 对如下问题十分感兴趣:

在一维空间中有点集 S S S 包含 n n n 个点,用什么算法能快速回答如下 q q q 次查询:
i i i 次查询给出点 p i p_i pi 和整数 k i k_i ki​ ,要求输出 S S S 中与点 p i p_i pi 距离第 k i k_i ki 近的点和 p i p_i pi 的距离。

距离:若点 u i u_i ui 坐标为 x i x_i xi v i v_i vi 坐标为 y i y_i yi​ ,则定义点 u i u_i ui​ 与点 v i v_i vi 的距离为 ∣ x i ​ − y i ​ ∣ ∣x_i​ −y_i​∣ xiyi

输入描述:
第一行两个整数 , n , q ( 1 ≤ n , q ≤ 2 × 1 0 5 ) n,q (1≤n,q≤2×10^5 ) n,q(1n,q2×105) 表示点集 S 的大小和查询次数。

第二行 n n n 个整数,第 i i i 个整数 a i ​ ( − 1 0 9 a_i​(−10^{9} ai(109 ≤ a i ​ ≤ 1 0 9 ) ≤a_i​ ≤10^{9} ) ai109)描述点集 S 里第 i i i 个点的坐标。

保证对于 ∀ i , j ( 1 ≤ i < j ≤ n ) 有 ≠ a i = a j ∀i,j (1≤i<j≤n) 有 ≠a_i =a_j i,j(1i<jn)=ai=aj 。接下来 q q q 行, 第 i i i 行两个整数 , x i x_i xi , k i k_i ki ( − 1 0 9 ≤ x i ≤ 1 0 9 , (−10^9 ≤x_i ≤10^9 , (109xi109,

1 ≤ k i ≤ n ) 1≤k_i ≤n) 1kin),表示 p i p_i pi 的坐标和需要查询距离 p i p_i pi k i k_i ki 近的结果。

输出描述:
输出 q q q 行,第 i i i 行一个整数,表示第 i i i 次查询的答案。


这里可以有很多种想法,比如说取差值,二分找点,定义排序规则,但是本题给出的数据范围只允许 q q q 询问内不超过 O ( N ) O(N) O(N) 的时间复杂度。

补充:lower_bound( arr.begin , arr.end , aim )返回数组中大于等于 a i m aim aim 的第一个元素的地址
upper_bound( arr.begin , arr.end , aim )返回数组中大于 a i m aim aim 的第一个元素的地址

对于lower_bound( arr.begin , arr.end , aim ) - arr,就代表了返回大于等于 a i m aim aim 的第一个元素的下标,upper_bound()同理。

那么可以二分距离

在排序之后,首先在外层二分取距离( m i d mid mid ),也就是枚举距离给出 x x x 的距离,然后使用lower_boundupper_bound去找到大于等于 x − m i d x-mid xmid 的第一个数对应的下标和大于 x + m i d x +mid x+mid 的第一个数对应的下标,然后检查他们(下标)的差值是否是大于等于k的,如果是,就去二分更小的距离,直到确定最终的第k个数和x相差的距离。

这里二分的意义是找到满足 x − m i d x-mid xmid x + m i d x+mid x+mid 中间满足有 k k k 个数的最小的距离

把那些数都反映成数轴上的数,距离也是以 x x x 为中心向两边扩散,如果这个范围能够涵盖到 k k k 个点,那么就说明离 x x x k k k 近的点一定就在他们其中。

在距离区间内的数的个数大于等于 k k k 的时候,就去搜更小的距离,也就是r = mid,如果距离区间内的数的个数小于 k k k 了,那么就要从大于 m i d mid mid 的点开始继续二分,即l = mid + 1,直到最后就会搜到一个最小的距离,使得其满足区间内有 k k k 个点。

搜到的这个距离一定保证是x距离某一个点的距离:因为如果你确定出来的是最小的包含 k k k 个数的距离,那么这个距离一定是刚刚好包含了 k k k 个数的,即第k近的数是在这个距离的边界上的。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+10;
const int mod = 1e9+7;
#define ll long longint a[N];
ll x,k;
int n,q;bool check(int mid){int LL = lower_bound(a+1,a+1+n,x - mid) - a;int RR = upper_bound(a+1,a+1+n,(ll)x + mid) - a;if(RR - LL >= k)return 1;else return 0;
}int main(){cin >> n >> q;for(int i = 1;i <= n;i++)cin >> a[i];sort(a+1,a+1+n);while(q--){cin >> x >> k;int l = 0,r = 2e9;while(l < r){int mid = (ll)l +r >> 1;if(check(mid))r = mid;else l = mid + 1;}cout << r << endl;}
}

题解部分已经结束,但是如果跳出这道题,我们想要找到数组中距离某一个数第k近的数还可以有以下的办法。

定义排序规则

如果我们有一个数组a[],并且我们想要找到给定任意一个 x x x 值的第 k k k 近的数,那么我们可以定义一个按照数组中每个元素按照其与 x x x 的差值的大小进行排序的办法。此方法主要适用于sort()函数

bool cmp(int a,int b){return abs(a - x) < abs(b - x);
}

双重二分+双指针

可以通过二分来找到距离 x x x 点最近的两个元素,之后取这两个元素中更接近于 x x x 的值为起点,使用双指针来向两边扩展。

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

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

相关文章

linux 自定义命令/别名

参考资料 Linux(Ubuntu)自定义命令的使用Linux/Ubuntu系统自定义Shell命令Ubuntu/Linux 操作系统 自定义命令 目录 一. 为路径取别名二. 修改.profile文件2.1 .profile简介2.2 需求2.3 修改.profile文件 三. 创建软链接 一. 为路径取别名 ⏹需求&#xff1a;有一个work文件夹…

前端面试问题汇总 - JS篇

1. JS的数据类型&#xff0c;如何判断js的数据类型&#xff1f; 数据类型有&#xff1a;Number&#xff0c;String&#xff0c;Boolean&#xff0c;Undefined&#xff0c;Null&#xff0c;Object&#xff0c;Array 其中&#xff0c;Number&#xff0c;String&#xff0c;Boolea…

NVM的安装与配置

目录 一、简介二、下载2.1、windows环境下载地址2.2、安装 三、配置3.1、查看可安装版本3.2、安装版本3.3、使用和切换版本3.4、模块配置 四、其他4.1、全局安装pnpm4.2、常用nvm命令 一、简介 NVM&#xff0c;全称为Node Version Manager&#xff0c;是一个流行的命令行工具&a…

VScode中C++里CompileDebug(winlinux)

C在vscode中配置 1.编译器环境搭建&#xff0c;c_cpp_properties.json生成 前置&#xff0c;mingw64添加入系统环境变量&#xff0c;编辑快捷键&#xff1a;ctrlshiftp修改选项&#xff1a;编译器路径 C:/mingw64/bin/g.exe IntelliSense 模式&#xff0c;这个应该是再说明一…

ucore 实验物理内存管理篇

实验汲取知识 基于段页式内存地址的转换机制页表的建立和使用方法物理内存的管理方法 首先了解如何发现系统中的物理内存&#xff1b;然后了解如何建立对物理内存的初步管理&#xff0c;即了解连续物理内存管理&#xff1b;最后了解页表相关的操作&#xff0c;即如何建立页表…

算法--目录

algorithm: 十种排序算法 二分法-各种应用 algorithm: 拓扑排序 算法中的背包问题 最长子序列问题 前缀和-解题集合 差分数组-解题

第41篇:有限状态机<四>

Q&#xff1a;本期我们介绍有限状态机的应用之二&#xff1a;米里状态机“1101”序列检测器。 A&#xff1a;摩尔状态机1101序列检测器有5个状态&#xff0c;而米里状态机只有4个状态。当状态为s_3且输入为1时&#xff0c;状态机输出1。这里输出与输入一起被标志在状态转移箭头…

vue3 动态class和style

1、需求&#xff1a;一个删除的弹窗&#xff0c;点击会提示“是否需要删除XXXXX&#xff08;name&#xff09;”&#xff0c;但是name不固定&#xff0c;所以删除弹窗的width不能写死。&#xff08;如果不设置width&#xff0c;本项目的弹窗会自适应变得特别长&#xff09;

mybatis自制插件+注解实现数据脱敏

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 mybatis自制插件注解实现数据脱敏 前言数据脱敏的实现方式构思从哪个地方进行脱敏&#xff1f;它怎么知道我什么数据需要脱敏 项目实现拦截器实现注解实现枚举实现效果图展示 前言 在数字时代&#x…

Java哈希查找(含面试大厂题和源码)

哈希查找&#xff08;Hash Search&#xff09;是一种基于哈希表&#xff08;Hash Table&#xff09;的数据查找方法。哈希表通过使用哈希函数将键&#xff08;Key&#xff09;映射到表中的位置来存储数据&#xff0c;从而实现快速的数据访问。哈希查找的效率通常取决于哈希函数…

hive了解系列一

“ 随着智能手机的普及&#xff0c;互联网时代红利的爆发&#xff0c;用户数量和产生的数据也越发庞大。为了解决这个问题&#xff0c;提高数据的使用价值。 Hadoop生态系统就被广泛得到应用。 在早期&#xff0c;Hadoop生态系统就是为处理如此大数据集而产生的一个合乎成本效益…

力扣第20题有效的括号

typedef char STDataType; //动态栈 #define allocator_may_return_null 1typedef struct ST {STDataType* _a;int _top;//栈顶元素int _capacity;//最大容量 }Stack; //初始化栈 void StackInit(Stack *pst);//入栈 void StackPush(Stack* pst, STDataType x);//出栈 void Sta…

英语写作中“大量的”“重大的”“显著的”substantial、considerable、significant的用法

一般“大量的”“重大的”会用a great number of 、a great amount of 、a plenty of 、great等&#xff0c;这些表达都过于trivial &#xff0c;用好substantial、considerable、significant 会对写作增色不少。 一、对于可数事物&#xff0c;用a considerable/substantial n…

小程序变更主体需要多久?

小程序迁移变更主体有什么作用&#xff1f;小程序迁移变更主体的好处有很多哦&#xff01;比如可以获得更多权限功能、公司变更或注销时可以保证账号的正常使用、收购账号后可以改变归属权或使用权等等。小程序迁移变更主体的条件有哪些&#xff1f;1、新主体必须是企业主体&am…

每日OJ题_BFS解决最短路①_力扣1926. 迷宫中离入口最近的出口

目录 力扣1926. 迷宫中离入口最近的出口 解析代码 力扣1926. 迷宫中离入口最近的出口 1926. 迷宫中离入口最近的出口 难度 中等 给你一个 m x n 的迷宫矩阵 maze &#xff08;下标从 0 开始&#xff09;&#xff0c;矩阵中有空格子&#xff08;用 . 表示&#xff09;和墙&…

Hibernate入门经典与注解式开发大全

本博文主要讲解介绍Hibernate框架&#xff0c;ORM的概念和Hibernate入门&#xff0c;相信你们看了就会使用Hibernate了! 什么是Hibernate框架&#xff1f; Hibernate是一种ORM框架&#xff0c;全称为 Object_Relative DateBase-Mapping&#xff0c;在Java对象与关系数据库之间建…

【uniapp踩坑记】使用z-paging组件,微信小程序端加载不出来问题解决

使用z-paging组件&#xff0c;h5端加载正常&#xff0c;微信小程序端显示空白 今天做分页列表&#xff0c;在插件市场找到了z-paging&#xff0c;照着示例代码写了进去&#xff0c;在h5端能正常使用&#xff0c;在小程序端一直显示空白 尝试过以下无效操作&#xff1a; 1.清除所…

Scrapy 框架基础

Scrapy框架基础Scrapy框架进阶 Scrapy 框架基础 【一】框架介绍 【1】简介 Scrapy是一个用于网络爬取的快速高级框架&#xff0c;使用Python编写他不仅可以用于数据挖掘&#xff0c;还可以用于检测和自动化测试等任务 【2】框架 官网链接https://docs.scrapy.org/en/late…

WPS二次开发系列:WPS SDk功能就概览

作者持续关注WPS二次开发专题系列&#xff0c;持续为大家带来更多有价值的WPS开发技术细节&#xff0c;如果能够帮助到您&#xff0c;请帮忙来个一键三连&#xff0c;更多问题请联系我&#xff08;QQ:250325397&#xff09; 作者通过深度测试使用了WPS SDK提供的Demo&#xff0…

给你的 vscode 扩展增加测试设置

文章目录 1. 目的2. vitest 作为 vscode 扩展单元测试3. vscode-test 集成测试4. 自定义 Runner 集成测试5. 小结 1. 目的 vscode 作为当前最多人使用的编辑器和开发工具&#xff0c;其最强大之处就是有成熟的插件社区&#xff0c;但是使用过程中难免就会遇到插件功能不够称心…