【线段树】2276. 统计区间中的整数数目

算法可以发掘本质,如:
一,若干师傅和徒弟互有好感,有好感的师徒可以结对学习。师傅和徒弟都只能参加一个对子。如何让对子最多。
二,有无限多1X2和2X1的骨牌,某个棋盘若干格子坏了,如何在没有坏的格子放足够多骨牌。
三,某个单色图,1表示前前景,0表示后景色。每次操作可以将一个1,变成0。如何在最少得操作情况下,使得没有两个1相邻(四连通)。
四,若干路人,有些人是熟人,如何选出最多的人参加实验。为了避免熟人影响实验的效果,参加的人不能是熟人。
一二是二分图的最大匹配,三是二分图的最小点覆盖,四是二分图最大独立集。 而这三者是等效问题。

本文涉及知识点

线段树

LeetCode2276. 统计区间中的整数数目

给你区间的 空 集,请你设计并实现满足要求的数据结构:
新增:添加一个区间到这个区间集合中。
统计:计算出现在 至少一个 区间中的整数个数。
实现 CountIntervals 类:
CountIntervals() 使用区间的空集初始化对象
void add(int left, int right) 添加区间 [left, right] 到区间集合之中。
int count() 返回出现在 至少一个 区间中的整数个数。
注意:区间 [left, right] 表示满足 left <= x <= right 的所有整数 x 。
示例 1:
输入
[“CountIntervals”, “add”, “add”, “count”, “add”, “count”]
[[], [2, 3], [7, 10], [], [5, 8], []]
输出
[null, null, null, 6, null, 8]
解释
CountIntervals countIntervals = new CountIntervals(); // 用一个区间空集初始化对象
countIntervals.add(2, 3); // 将 [2, 3] 添加到区间集合中
countIntervals.add(7, 10); // 将 [7, 10] 添加到区间集合中
countIntervals.count(); // 返回 6
// 整数 2 和 3 出现在区间 [2, 3] 中
// 整数 7、8、9、10 出现在区间 [7, 10] 中
countIntervals.add(5, 8); // 将 [5, 8] 添加到区间集合中
countIntervals.count(); // 返回 8
// 整数 2 和 3 出现在区间 [2, 3] 中
// 整数 5 和 6 出现在区间 [5, 8] 中
// 整数 7 和 8 出现在区间 [5, 8] 和区间 [7, 10] 中
// 整数 9 和 10 出现在区间 [7, 10] 中
提示:
1 <= left <= right <= 109
最多调用 add 和 count 方法 总计 105
调用 count 方法至少一次

线段树

由于本题无法离散化,所以用数组内存必定会超,只能用哈希映射或二叉树动态开点,二叉树的性能略好,就用二叉树。就算用二叉树也刚刚能过。
区间修改,查询全部。
由于只用到了查询全部,所以查询可以不实现。
save 记录 整个区间 在题目所在区间的数量。
叶子save 的值为1,表示在至少一个区间。0,表示不在任何区间。

template<class TSave=int, class TRecord =int >
class CMyTreeRangeLineTree : public CTreeRangeLineTree<TSave, TRecord>
{	
public:using CTreeRangeLineTree<TSave, TRecord>::CTreeRangeLineTree;
protected:virtual void OnQuery(TSave& save) override{}virtual void OnUpdate(TSave& save, int iSaveLeft, int iSaveRight, const TRecord& update) override{ save = update*(iSaveRight-iSaveLeft+1);}virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) override{par = left + r;}virtual void OnUpdateRecord(TRecord& old, const TRecord& newRecord) override{old = newRecord;}
};

本题只会更新1,如果需要考虑取消,也就是更新为0。需要将懒标记的默认值设置成-1。
CountIntervals():m_treeLine(1,1’000’000’000,0,-1){

}

代码

template<class TSave, class TRecord >
class CRangUpdateLineTree 
{
protected:virtual void OnQuery(TSave& save) = 0;virtual void OnUpdate(TSave& save, int iSaveLeft,int iSaveRight, const TRecord& update) = 0;virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) = 0;virtual void OnUpdateRecord(TRecord& old, const TRecord& newRecord) = 0;
};template<class TSave, class TRecord >
class CTreeRangeLineTree : public CRangUpdateLineTree<TSave, TRecord>
{
protected:struct CTreeNode{int Cnt()const { return m_iMaxIndex - m_iMinIndex + 1; }int m_iMinIndex;int m_iMaxIndex;TRecord record;TSave data;CTreeNode* m_lChild = nullptr, * m_rChild = nullptr;};CTreeNode* m_root;TSave m_tDefault;TRecord m_tRecordDef;
public:CTreeRangeLineTree(int iMinIndex, int iMaxIndex, TSave tDefault,TRecord tRecordDef) {m_tDefault = tDefault;m_tRecordDef = tRecordDef;m_root = CreateNode(iMinIndex, iMaxIndex);}void Update(int iLeftIndex, int iRightIndex, TRecord value){Update(m_root, iLeftIndex, iRightIndex, value);}TSave QueryAll() {return m_root->data;}void Query(int leftIndex, int leftRight) {Query(m_root, leftIndex, leftRight);}
protected:void Query(CTreeNode* node, int iQueryLeft, int iQueryRight) {if ((node->m_iMinIndex >= iQueryLeft) && (node->m_iMaxIndex <= iQueryRight)) {this->OnQuery(node->data);return;}if (1 == node->Cnt()) {//没有子节点return;}CreateChilds(node);Fresh(node);const int mid = node->m_iMinIndex + (node->m_iMaxIndex - node->m_iMinIndex) / 2;if (mid >= iQueryLeft) {Query(node->m_lChild, iQueryLeft, iQueryRight);}if (mid + 1 <= iQueryRight) {Query(node->m_rChild, iQueryLeft, iQueryRight);}}void Update(CTreeNode* node, int iOpeLeft, int iOpeRight, TRecord value){const int& iSaveLeft = node->m_iMinIndex;const int& iSaveRight = node->m_iMaxIndex;if ((iOpeLeft <= iSaveLeft) && (iOpeRight >= iSaveRight)){this->OnUpdate(node->data, iSaveLeft, iSaveRight, value);this->OnUpdateRecord(node->record, value);return;}if (1 == node->Cnt()) {//没有子节点return;}CreateChilds(node);Fresh(node);const int mid = node->m_iMinIndex + (node->m_iMaxIndex - node->m_iMinIndex) / 2;if (mid >= iOpeLeft) {this->Update(node->m_lChild, iOpeLeft, iOpeRight, value);}if (mid + 1 <= iOpeRight) {this->Update(node->m_rChild, iOpeLeft, iOpeRight, value);}// 如果有后代,至少两个后代this->OnUpdateParent(node->data, node->m_lChild->data, node->m_rChild->data,node->m_iMinIndex,node->m_iMaxIndex);}void CreateChilds(CTreeNode* node) {if (nullptr != node->m_lChild) { return; }const int iSaveLeft = node->m_iMinIndex;const int iSaveRight = node->m_iMaxIndex;const int mid = iSaveLeft + (iSaveRight - iSaveLeft) / 2;node->m_lChild = CreateNode(iSaveLeft, mid);node->m_rChild = CreateNode(mid + 1, iSaveRight);}CTreeNode* CreateNode(int iMinIndex, int iMaxIndex) {CTreeNode* node = new CTreeNode;node->m_iMinIndex = iMinIndex;node->m_iMaxIndex = iMaxIndex;node->data = m_tDefault;node->record = m_tRecordDef;return node;}void Fresh(CTreeNode* node){if (m_tRecordDef == node->record){return;}CreateChilds(node);Update(node->m_lChild, node->m_lChild->m_iMinIndex, node->m_lChild->m_iMaxIndex, node->record);Update(node->m_rChild, node->m_rChild->m_iMinIndex, node->m_rChild->m_iMaxIndex, node->record);node->record = m_tRecordDef;}
};template<class TSave=int, class TRecord =int >
class CMyTreeRangeLineTree : public CTreeRangeLineTree<TSave, TRecord>
{	
public:using CTreeRangeLineTree<TSave, TRecord>::CTreeRangeLineTree;
protected:virtual void OnQuery(TSave& save) override{}virtual void OnUpdate(TSave& save, int iSaveLeft, int iSaveRight, const TRecord& update) override{ save = update*(iSaveRight-iSaveLeft+1);}virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, int iSaveLeft, int iSaveRight) override{par = left + r;}virtual void OnUpdateRecord(TRecord& old, const TRecord& newRecord) override{old = newRecord;}
};class CountIntervals {
public:CountIntervals():m_treeLine(1,1'000'000'000,0,0){}void add(int left, int right) {m_treeLine.Update(left, right,1);}int count() {return m_treeLine.QueryAll();}CMyTreeRangeLineTree<> m_treeLine;
};

测试用例

CountIntervals countIntervals ; // 用一个区间空集初始化对象countIntervals.add(2, 3);  // 将 [2, 3] 添加到区间集合中countIntervals.add(7, 10); // 将 [7, 10] 添加到区间集合中auto res = countIntervals.count();    // 返回 6// 整数 2 和 3 出现在区间 [2, 3] 中// 整数 7、8、9、10 出现在区间 [7, 10] 中Assert(6, res);countIntervals.add(5, 8);  // 将 [5, 8] 添加到区间集合中res = countIntervals.count();    // 返回 8// 整数 2 和 3 出现在区间 [2, 3] 中// 整数 5 和 6 出现在区间 [5, 8] 中// 整数 7 和 8 出现在区间 [5, 8] 和区间 [7, 10] 中// 整数 9 和 10 出现在区间 [7, 10] 中Assert(8, res);

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步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

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

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

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

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

相关文章

BJT 和 FET的知识点以及区别

一、晶体管的介绍 晶体管是一种三端半导体器件&#xff0c;它是一种用于大多数电子设备的有源器件。晶体管可根据需要用作绝缘体和导体。我们可以将晶体管用作开关和放大器。它可以与其他电路元件一起使用&#xff0c;并且能够放大电流和电压。我们可以将晶体管分为两种类型&am…

锐化空间滤波器--二阶微分图像增强(提高清晰度的另一种方式)

书上一阶微分的定义可以理解&#xff0c;毕竟这里不死数学上的曲线的概念&#xff0c;而是像素点上的曲线。所以&#xff0c;不同于数学的严格单调递增曲线的导数是大于等于零&#xff0c;这里的严格单调递增曲线&#xff0c;只能是大于零。 至于二阶微分的定义&#xff0c;就…

HarmonyOS实战开发-图片编辑、使用 TextArea 实现多文本输入

介绍 本示例使用 TextArea 实现多文本输入&#xff0c;使用 ohos.app.ability.common 依赖系统的图库引用&#xff0c;实现在相册中获取图片&#xff0c;使用 ohos.multimedia.image 生成pixelMap&#xff0c;使用pixelMap的scale()&#xff0c;crop()&#xff0c;rotate()接口…

idea 中运行spring boot 项目报 Command line is too long的解决办法。

Command line is too long 在这里选择edit configures 选择shrten command line , 选择 jar manifest 运行即可。

解决vue启动项目报错:npm ERR! Missing script: “serve“【详细清晰版】

目录 问题描述问题分析和解决情况一解决方法情况二&#xff08;常见于vue3&#xff09;解决方法情况三解决方法 问题描述 在启动vue项目时通常在控制台输入npm run serve 但是此时出现如下报错&#xff1a; npm ERR! Missing script: "serve" npm ERR! npm ERR! T…

IJKPLAYER源码分析-iOS端显示

1 简介 1.1 EAGL(Embedded Apple Graphics Library) 与Android系统使用EGL连接OpenGL ES与原生窗口进行surface输出类似&#xff0c;iOS则用EAGL将CAEAGLLayer作为OpenGL ES输出目标。 与 Android EGL 不同的是&#xff0c;iOS EAGL 不会让应用直接向 BackendFrameBuffer 和 F…

KKVIEW远程远程访问家里电脑

远程访问家里电脑&#xff1a;简易指南与价值所在 在数字化时代&#xff0c;电脑已成为我们日常生活和工作中不可或缺的工具。有时&#xff0c;我们可能在外出时急需访问家中电脑里的某个文件或应用&#xff0c;这时&#xff0c;远程访问家里电脑就显得尤为重要。本文将简要介…

微服务-7 Docker

一、镜像、容器、仓库 容器是镜像的实例&#xff0c;仓库中存储着镜像。 二、镜像的操作 三、容器的操作 创建容器停止容器&#xff0c;查看后发现没有了(docker ps 默认只展示没有停止的) docker ps -a (可以展示运行中和停止的镜像)删除容器&#xff1a;(docker rm 不能删除…

突破界限 千视将在 NAB 2024 展会上展示领先的 AV over IP 技术

突破界限&#xff01;千视将在 NAB 2024 展会上展示领先的 AV over IP技术 作为AV over IP领域的先驱者&#xff0c;Kiloview将于2024年4月14日至17日在NAB展会&#xff08;展台号&#xff1a;SU6029&#xff09;隆重登场&#xff0c;展示我们领先业界的AV over IP产品、解决方…

【问题】解决1130-Host‘ ‘is not allowed to connect to this MySQL 本地无法连接服务器的数据库

【问题】解决1130-Host‘ ‘is not allowed to connect to this MySQL 本地无法连接服务器的数据库 原因: 默认mysql只允许 localhost 本地访问数据库, 解决方法 将 localhost 改为 % 所有 第一步 回车 输入密码 mysql -u root -p 第二步 切换数据库 use mysql 第三步 更新所…

Day96:云上攻防-云原生篇Docker安全系统内核版本漏洞CDK自动利用容器逃逸

目录 云原生-Docker安全-容器逃逸&系统内核漏洞 云原生-Docker安全-容器逃逸&docker版本漏洞 CVE-2019-5736 runC容器逃逸(需要管理员配合触发) CVE-2020-15257 containerd逃逸(启动容器时有前提参数) 云原生-Docker安全-容器逃逸&CDK自动化 知识点&#xff1…

Ubuntu下配置Android NDK环境

Android-NDK的下载 下载Android-NDK wget -c http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin 执行bin文件&#xff08;即解压&#xff09; ./android-ndk-r10c-linux-x86_64.bin Android-NDK的配置 要想使用Android-NDK&#xff0c;还需要进行环境变量…

GitHub repository - Code - Issues - Pull Requests - Wiki

GitHub repository - Code - Issues - Pull Requests - Wiki 1. Code2. Issues3. Pull Requests4. WikiReferences 1. Code 显示该仓库中的文件列表。仓库名下方是该仓库的简单说明和 URL. 2. Issues 用于 BUG 报告、功能添加、方向性讨论等&#xff0c;将这些以 Issue 形式进…

less+rem适配+媒体查询布局(主流)

rem适配布局 一.rem基础二.媒体查询1.概念2.语法&#xff08;1&#xff09;.mediatype查询类型&#xff08;2&#xff09;.关键字&#xff08;3&#xff09;.媒体特性&#xff08;4&#xff09;.应用 3.媒体查询rem实现元素动态大小变化4.引入资源&#xff08;针对不同媒体查询…

JSONP是跨域资源共享的古老技术吗

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

前端和后端解决跨域问题的方法

目前很多java web开发都是采用前后端分离框架进行开发&#xff0c;相比于单体项目容易产生跨域问题。 一、跨域问题CORS 1.什么是跨域问题&#xff1f; 后端接收到请求并返回结果了&#xff0c;浏览器把这个响应拦截了。 2.跨域问题是怎么产生的&#xff1f; 浏览器基于同源…

spring boot 集成rocketMq + 基本使用

1. RocketMq基本概念 1. NameServer 每个NameServer结点之间是相互独立&#xff0c;彼此没有任何信息交互 启动NameServer。NameServer启动后监听端口&#xff0c;等待Broker、Producer、Consumer连接&#xff0c; 相当于一个路由控制中心。主要是用来保存topic路由信息&#…

ETL中如何运用好MQ消息集成

一、ETL的主要作用 ETL&#xff08;Extract, Transform, Load&#xff09;是数据仓库中的关键环节&#xff0c;其主要作用是将数据从源系统中抽取出来&#xff0c;经过转换和清洗后加载到数据仓库中。具体而言&#xff1a; Extract&#xff08;抽取&#xff09;&#xff1a;从…

Ubuntu 安装Java、Git、maven、Jenkins等持续集成环境

Ubuntu 持续集成 安装OpenJdk 查看所有可安装的 JDK 版本 apt list OpenJDK\*使用 apt 安装 JDK&#xff08;以 11为例&#xff09;,最好是用11&#xff0c;java8对应的jenkins会有兼容问题。 sudo apt install openjdk-11-jdk openjdk-11-jre安装成功后&#xff0c;可以使用以…

WS2812B彩灯

目录 1、介绍 2、参数 3、引脚功能 4、应用电路 5、Code 1、介绍 WS2812是一种智能控制LED灯源&#xff0c;集成了控制电路和RGB芯片在一个5050封装组件中。它的主要特点和技术规格如下&#xff1a; 集成设计&#xff1a;WS2812将控制电路和RGB芯片集成在同一个封装中&…