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

C++二分查找:统计点对的数目

本题其它解法

C++双指针算法:统计点对的数目

本周推荐阅读

C++二分算法:得到子序列的最少操作次数

本文涉及的基础知识点

二分查找算法合集

题目

给你一个无向图,无向图由整数 n ,表示图中节点的数目,和 edges 组成,其中 edges[i] = [ui, vi] 表示 ui 和 vi 之间有一条无向边。同时给你一个代表查询的整数数组 queries 。
第 j 个查询的答案是满足如下条件的点对 (a, b) 的数目:
a < b
cnt 是与 a 或者 b 相连的边的数目,且 cnt 严格大于 queries[j] 。
请你返回一个数组 answers ,其中 answers.length == queries.length 且 answers[j] 是第 j 个查询的答案。
请注意,图中可能会有 多重边 。
示例 1:
输入:n = 4, edges = [[1,2],[2,4],[1,3],[2,3],[2,1]], queries = [2,3]
输出:[6,5]
在这里插入图片描述

解释:每个点对中,与至少一个点相连的边的数目如上图所示。
answers[0] = 6。所有的点对(a, b)中边数和都大于2,故有6个;
answers[1] = 5。所有的点对(a, b)中除了(3,4)边数等于3,其它点对边数和都大于3,故有5个。
示例 2:
输入:n = 5, edges = [[1,5],[1,5],[3,4],[2,5],[1,3],[5,1],[2,3],[2,5]], queries = [1,2,3,4,5]
输出:[10,10,9,8,6]
参数范围
2 <= n <= 2 * 104
1 <= edges.length <= 105
1 <= ui, vi <= n
ui != vi
1 <= queries.length <= 20
0 <= queries[j] < edges.length

分析

时间复杂度

每个查询的时间复杂度是O(nlogn+m)。m的边数。

步骤

每个查询分两步:
一,和a或b相连的边数,严格大于iQue的点对数量。注意,同时和a和b相连算两次,只和a或b相连算一次。
二,枚举各边。如果符合第一步,扣除本边数量后,不再符合题意则减掉。本解法在预处理阶段确保v[0]大于v[1]。
注意:本解题将a和b都减一,这样其范围为:[0,n)。

变量解释

m_vNodeToCountm_vNodeToCount[i]=x,有x条边和i相连
m_vCountsm_vNodeToCount的升序,第一步只考虑和a或b相连的边数,不需要知道a和b的具体值
m_mMaskCount各边数量,key是a和b的编码,value是数量

代码

核心代码

class Solution {
public:vector<int> countPairs(int n, vector<vector<int>>& edges, vector<int>& queries) {		m_iN = n;m_vNodeToCount.resize(n);for (auto& v : edges){if (v[0] < v[1]){swap(v[0], v[1]);}v[0]--;v[1]--;			m_vNodeToCount[v[0]]++;m_vNodeToCount[v[1]]++;m_mMaskCount[Mask(v[0], v[1])]++;}m_vCounts = m_vNodeToCount;sort(m_vCounts.begin(), m_vCounts.end());vector<int> vRet;for (const auto& que : queries){vRet.emplace_back(Query(que));}return vRet;}int Query(int iQue)const{int iNum = 0;// 包括a或b的边数大于iQue的数量,(a,b)和(b,a)会重复结算for (auto left = m_iN - 1; left >= 0 ; left--){		iNum += m_vCounts.end() - std::upper_bound(m_vCounts.begin()+left+1, m_vCounts.end(),iQue-m_vCounts[left]);}//扣处重复数量for (const auto& [iMask, iNum1] : m_mMaskCount){auto [a, b] = Parse(iMask);const int tmp = m_vNodeToCount[a] + m_vNodeToCount[b] - iQue;if (tmp > 0 ){if (tmp <= iNum1){iNum--;}}}	return iNum;}int Mask(int a, int b){return a * m_iUnit + b;}std::pair<int,int> Parse(const int iMask)const{return std::make_pair(iMask / m_iUnit, iMask % m_iUnit);}const int m_iUnit = 1000 * 100;unordered_map<int, int> m_mMaskCount;vector<int> m_vNodeToCount;vector<int> m_vCounts;int m_iN;
};

测试用例

template <class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template <class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}
}int main()
{int n;vector<vector<int>> edges;vector<int> queries;vector<int> res;{	n = 4;edges = { {1,2},{2,4},{1,3},{2,3},{2,1} };queries = { 2,3 };Solution slu;res = slu.countPairs(n, edges, queries);Assert(res, vector<int>{6, 5});}{n = 5;edges = { {1,5},{1,5},{3,4},{2,5},{1,3},{5,1},{2,3},{2,5} };queries = { 1,2,3,4,5 };Solution slu;res = slu.countPairs(n, edges, queries);Assert(res, vector<int>{10, 10, 9, 8, 6});}//CConsole::Out(res);
}

2023年3月版代码

class Solution {
public:
vector countPairs(int n, vector<vector>& edges, vector& queries) {
m_vDeg.resize(n + 1);
m_iN = n;
for (const auto& v : edges)
{
m_vDeg[v[0]]++;
m_vDeg[v[1]]++;
m_mEdgeNums[min(v[0], v[1])m_llMul + max(v[0], v[1])]++;
}
vector vRet;
for (const auto& q : queries)
{
vRet.push_back(Query1(q) - Query2(q));
}
return vRet;
}
long long Query1(int iQuery)
{
CTreeArr tree(1000
100 + 1);
long long iRet = 0;
for (int i = 1; i <= m_iN; i++)
{
const int iMin = iQuery - m_vDeg[i];
const int iLessEqualNum = (iMin>=0) ? tree.Sum(iMin ) : 0;
iRet += (i - 1) - iLessEqualNum;
tree.Add(m_vDeg[i],1);
}
return iRet;
}
long long Query2(int iQuery)
{
long long llSub = 0;
for (auto it : m_mEdgeNums)
{
const int iNum1 = m_vDeg[it.first%m_llMul] + m_vDeg[it.first/m_llMul];
if (iNum1 <= iQuery)
{
continue;
}
if (iNum1 - it.second <= iQuery)
{
llSub++;
}
}
return llSub;
}
long long m_llMul = 1000 * 100;
vector m_vDeg;
std::unordered_map<long long, int> m_mEdgeNums;
int m_iN;
};

2023年7月版代码

class Solution {
public:
vector countPairs(int n, vector<vector>& edges, vector& queries) {
m_vConnectNums.resize(n + 1);
m_n = n;
for (const auto& v : edges)
{
m_vConnectNums[v[0]]++;
m_vConnectNums[v[1]]++;
m_mEdgeMaskNum[ToMask(v)]++;
}
m_iMaxSize = *std::max_element(m_vConnectNums.begin(), m_vConnectNums.end());
vector vRet;
for (const auto& que : queries)
{
vRet.emplace_back(Query(que));
}
return vRet;
}
int Query(const int iQuery)
{
CTreeArr treeArr(m_iMaxSize + 1);
int iRet = 0;
for (int i = 1; i <= m_n; i++)
{
const int iCurSize = m_vConnectNums[i];
int iMin = iQuery - iCurSize;
if (iMin < 0)
{
iRet += (i - 1);
}
else if (iMin >= m_iMaxSize)
{
}
else
{
const int iSum1 = treeArr.Sum(m_iMaxSize);
const int iSum2 = treeArr.Sum(iMin);
iRet += iSum1 - iSum2;
}
treeArr.Add(iCurSize, 1);
}
for (const auto& it : m_mEdgeMaskNum)
{
const int iNum = m_vConnectNums[it.first / 100000] + m_vConnectNums[it.first % 100000];
if (iNum <= iQuery)
{
continue;
}
if (iNum - it.second <= iQuery)
{
iRet–;
}
}
return iRet;
}
int ToMask(const vector& v)
{
return min(v[0], v[1]) * 100000 + max(v[0], v[1]);
}
std::unordered_map<int, int> m_mEdgeMaskNum;
vector m_vConnectNums;
int m_n;
int m_iMaxSize;
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

相关文章:

C++二分查找:统计点对的数目

本题其它解法 C双指针算法&#xff1a;统计点对的数目 本周推荐阅读 C二分算法&#xff1a;得到子序列的最少操作次数 本文涉及的基础知识点 二分查找算法合集 题目 给你一个无向图&#xff0c;无向图由整数 n &#xff0c;表示图中节点的数目&#xff0c;和 edges 组成…...

播放器开发(二):了解FFmpeg与SDL常用对象和函数

学习课题&#xff1a;逐步构建开发播放器【QT5 FFmpeg6 SDL2】 前言 这一篇内容就是简单的了解一遍一些常用的函数名称和作用&#xff0c;混个眼熟。 能看源码的就去看源码&#xff01;&#xff01;&#xff01; 能看源码的就去看源码&#xff01;&#xff01;&#xff01; …...

【数据库】基于排序算法的去重,集合与包的并,差,交,连接操作实现原理,执行代价以及优化

基于两趟排序的其它操作 ​专栏内容&#xff1a; 手写数据库toadb 本专栏主要介绍如何从零开发&#xff0c;开发的步骤&#xff0c;以及开发过程中的涉及的原理&#xff0c;遇到的问题等&#xff0c;让大家能跟上并且可以一起开发&#xff0c;让每个需要的人成为参与者。 本专栏…...

Redis 主从架构,Redis 分区,Redis哈希槽的概念,为什么要做Redis分区

文章目录 Redis 主从架构redis replication 的核心机制redis 主从复制的核心原理过程原理Redis集群的主从复制模型是怎样的&#xff1f;生产环境中的 redis 是怎么部署的&#xff1f;机器是什么配置&#xff1f;你往内存里写的是什么数据&#xff1f;说说Redis哈希槽的概念&…...

极客大挑战2023 Web方向题解wp 全

最后排名 9/2049。 玩脱了&#xff0c;以为28结束&#xff0c;囤的一些flag没交上去。我真该死啊QAQ EzHttp 前言&#xff1a;这次极客平台太安全了谷歌不给抓包&#xff0c;抓包用burp自带浏览器。 密码查看源码->robots.txt->o2takuXX’s_username_and_password.txt获…...

kafka开发环境搭建

文章目录 1 安装java环境1.1 下载linux下的安装包1.2 解压缩安装包1.3 解压后的文件移到/usr/lib目录下1.4 配置java环境变量 2 kafka的安装部署2.1 下载安装kafka2.2 配置和启动zookeeper2.3 启动和停止kafka 1 安装java环境 1.1 下载linux下的安装包 &#xff08;1&#xf…...

Python大数据考题

Python大数据考题&#xff1a; 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都得去找开发&#xff0c;测开 测开的话&#xff0c;你就得学数据库&#xff0c;sql&#xff0c;oracle&#xff0c;尤其sql要…...

才聚免费为你招聘,用人单位看过来!

才聚团队从1998年开始从事项目管理的推广工作&#xff0c;20多年来培训学员超30万人次&#xff0c;分布全国各地、服务企业超过5000家。拥有大批 PMP &#xff08;项目管理专业人员资格&#xff09; NPDP&#xff08;产品经理国际资格&#xff09; 软考 &#xff08;信息系统…...

【SpringCloud】微服务的扩展性及其与 SOA 的区别

一、微服务的扩展性 由上一篇文章&#xff08;没看过的可点击传送阅读&#xff09;可知&#xff0c; 微服务具有极强的可扩展性&#xff0c;这些扩展性包含以下几个方面&#xff1a; 性能可扩展&#xff1a;性能无法完全实现线性扩展&#xff0c;但要尽量使用具有并发性和异步…...

从零带你底层实现unordered_map (2)

&#x1f4af; 博客内容&#xff1a;从零带你实现unordered_map &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准C后端工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家…...

打造企业AI数字人专属IP的重要性

在数字化时代&#xff0c;企业数字人专属IP的打造成为了企业品牌建设的重要组成部分。企业数字人专属IP是指是利用人工智能技术实现与真人直播形象的1:1克隆&#xff0c;即克隆出一个数字化的真人形象&#xff0c;作为独有的企业数字人形象&#xff0c;可以用于产品推广、品牌宣…...

docker容器的生命周期管理常用命令

容器的生命周期管理命令 docker create &#xff1a;创建一个新的容器但不启动它 docker create nginx docker run :创建一个新的容器并运行一个命令 常用选项&#xff1a; 常用选项1. --add-host&#xff1a;容器中hosts文件添加 host:ip 映射记录 2. -a, --attach&#…...

CF 1900B Laura and Operations 学习笔记

原题链接 传送门 题意 输入三个数字a,b,c表示1&#xff0c;2&#xff0c;3的数目&#xff0c;也就是说有a个1&#xff0c;b个2&#xff0c;c个3&#xff0c;每一次可以删除两个不同的数字&#xff0c;增加一个剩下的数字&#xff0c;比如说删除1和3&#xff0c;增加2&#x…...

Linux学习笔记6-串口应用

到现在为止都是在开发板上运行的裸机程序&#xff0c;相当于之前学习STM32单片机时走过的路&#xff0c;还没有真正进入到核心的驱动开发部分&#xff0c;但这都是基础&#xff0c;所以慢慢来不着急。 接下来进入串口通信的学习&#xff0c;和GPIO一样&#xff0c;也是和单片机…...

ubuntu下如何查看.gz压缩包中的内容,以及grep过滤查找文件中的某些内容

1、查看压缩包file.gz中的全部内容 $ zcat file.gz 2、对一个.gz的压缩包解压缩 $ gunzip file.gz 3、过滤查找文件中的某些内容 $ grep "Hello" file.txt 注&#xff1a;我通常先解压&#xff0c;然后再grep 4、过滤查找文件中的内容&#xff0c;并显示其上下3行…...

AI 重构工业制造的故事 我们从大模型开始讲起

在数字化浪潮的推动下&#xff0c;工业制造领域正经历着一场前所未有的变革。人工智能&#xff08;AI&#xff09;作为这场变革的关键推动者之一&#xff0c;正以惊人的速度颠覆传统制造业。而大模型作为AI时代最先进的科技工具之一&#xff0c;或将成为引领这场变革的利器&…...

easyExcel 注解开发 快速以及简单上手 以及包含工具类

easyExcel 简单快速使用 1. mevan 这里版本我这里选的是 poi 4.1.2和 ali的easyexcel 的 3.3.1。 因为阿里easy是根据poi的依赖开发的有关系&#xff0c;两者需要对应要不然就会有很多bug和错误在运行时发生。需要版本对应&#xff0c;然而就是easy的代码也会有bug这个版本是比…...

VS2010配置opencv2.4.10

1.下载opencv2.4.10&#xff0c;百度网盘链接如下&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1UdoQJbRUEB_G2urT703xYQ 提取码&#xff1a;7lbd 2.运行opencv-2.4.10.exe&#xff0c;将文件提取到一个自定义目录里&#xff1a; 3.添加系统环境变量 在“系统变量…...

Android:控制按键灯亮灭【button-backlight】

/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java 1.导包 import java.io.DataOutputStream; import java.io.FileOutputStream; Handler mHandler3; 2.新建handler对象 public void init(Context context, IWindowManager windowMan…...

1、nmap常用命令

文章目录 1. 主机存活探测2. 常见端口扫描、服务版本探测、服务器版本识别3. 全端口&#xff08;TCP/UDP&#xff09;扫描4. 最详细的端口扫描5. 三种TCP扫描方式&#xff08;1&#xff09;TCP connect 扫描&#xff08;2&#xff09;TCP SYN扫描&#xff08;3&#xff09;TCP …...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别

【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而&#xff0c;传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案&#xff0c;能够实现大范围覆盖并远程采集数据。尽管具备这些优势&#xf…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...