【离散化 二维差分】850. 矩形面积 II

news2024/11/26 14:57:27

本文涉及知识点

离散化 二维差分

LeetCode850. 矩形面积 II

给你一个轴对齐的二维数组 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标, (xi1, yi1) 是该矩形 左下角 的坐标, (xi2, yi2) 是该矩形 右上角 的坐标。
计算平面中所有 rectangles 所覆盖的 总面积 。任何被两个或多个矩形覆盖的区域应只计算 一次 。
返回 总面积 。因为答案可能太大,返回 109 + 7 的 模 。

示例 1:
在这里插入图片描述

输入:rectangles = [[0,0,2,2],[1,0,2,3],[1,0,3,1]]
输出:6
解释:如图所示,三个矩形覆盖了总面积为 6 的区域。
从(1,1)到(2,2),绿色矩形和红色矩形重叠。
从(1,0)到(2,3),三个矩形都重叠。
示例 2:

输入:rectangles = [[0,0,1000000000,1000000000]]
输出:49
解释:答案是 1018 对 (109 + 7) 取模的结果, 即 49 。

提示:

1 <= rectangles.length <= 200
rectanges[i].length = 4
0 <= xi1, yi1, xi2, yi2 <= 109

离散化、二维差分

注意: 忽略xi1 等于 xi2或yi1等于yi2得。确保xi1<xi2和yi1<yi2。
一,利用vCodex将所有xi1,xi2编码。
二,vCodey将所有yi1,yi2编码。
三,利用二维差分记录那些点(编码)被覆盖。
令点x1,y1被覆盖则 面积为(vCodex[x1+1]-vCodex[x1])*(vCodey[y1+1]-vCodey[y1])

代码

核心代码



template<int MOD = 1000000007>
class C1097Int
{
public:
	C1097Int(long long llData = 0) :m_iData(llData% MOD)
	{

	}
	C1097Int  operator+(const C1097Int& o)const
	{
		return C1097Int(((long long)m_iData + o.m_iData) % MOD);
	}
	C1097Int& operator+=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData + o.m_iData) % MOD;
		return *this;
	}
	C1097Int& operator-=(const C1097Int& o)
	{
		m_iData = (m_iData + MOD - o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator-(const C1097Int& o)
	{
		return C1097Int((m_iData + MOD - o.m_iData) % MOD);
	}
	C1097Int  operator*(const C1097Int& o)const
	{
		return((long long)m_iData * o.m_iData) % MOD;
	}
	C1097Int& operator*=(const C1097Int& o)
	{
		m_iData = ((long long)m_iData * o.m_iData) % MOD;
		return *this;
	}
	C1097Int  operator/(const C1097Int& o)const
	{
		return *this * o.PowNegative1();
	}
	C1097Int& operator/=(const C1097Int& o)
	{
		*this /= o.PowNegative1();
		return *this;
	}
	bool operator==(const C1097Int& o)const
	{
		return m_iData == o.m_iData;
	}
	bool operator<(const C1097Int& o)const
	{
		return m_iData < o.m_iData;
	}
	C1097Int pow(long long n)const
	{
		C1097Int iRet = 1, iCur = *this;
		while (n)
		{
			if (n & 1)
			{
				iRet *= iCur;
			}
			iCur *= iCur;
			n >>= 1;
		}
		return iRet;
	}
	C1097Int PowNegative1()const
	{
		return pow(MOD - 2);
	}
	int ToInt()const
	{
		return m_iData;
	}
private:
	int m_iData = 0;;
};
class CDiscretize //离散化
{
public:
	CDiscretize(vector<int> nums)
	{
		sort(nums.begin(), nums.end());
		nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
		m_nums = nums;
		for (int i = 0; i < nums.size(); i++)
		{
			m_mValueToIndex[nums[i]] = i;
		}
	}
	int operator[](const int value)const
	{
		auto it = m_mValueToIndex.find(value);
		if (m_mValueToIndex.end() == it)
		{
			return -1;
		}
		return it->second;
	}
	int size()const
	{
		return m_mValueToIndex.size();
	}
	vector<int> m_nums;
protected:	
	unordered_map<int, int> m_mValueToIndex;
};


template<class T = int >
class CDiff2
{
public:
	CDiff2(int r, int c):m_iR(r),m_iC(c) {
		m_vDiff.assign(m_iR, vector<T>(m_iC));
	}
	void Set(int r1, int c1, int r2Exinc, int c2Exinc,int iAdd) {
		m_vDiff[r1][c1] += iAdd;
		m_vDiff[r2Exinc][c2Exinc] += iAdd;
		m_vDiff[r1][c2Exinc] -= iAdd;
		m_vDiff[r2Exinc][c1] -= iAdd;
	}
	vector<vector<T>> Ans()const {
		vector<vector<T>> res(m_iR, vector<T>(m_iC));
		vector<T> vCols(m_iC);
		for (int r = 0; r < m_iR; r++) {
			T iSum = 0;
			for (int c = 0; c < m_iC; c++) {
				vCols[c] += m_vDiff[r][c];
				iSum += vCols[c];
				res[r][c] = iSum;
			}
		}
		return res;
	}
	
	const int m_iR, m_iC;
protected:
	vector<vector<T>> m_vDiff;
};
class Solution {
public:
	int rectangleArea(vector<vector<int>>& rectangles) {
		vector<vector<int>> tmp;
		vector<int> xs, ys;
		for (auto& v : rectangles) {
			if ((v[0] == v[2]) || (v[1] == v[3])) { continue; }
			if (v[0] > v[2]) { swap(v[0], v[2]); }
			if (v[1] > v[3]) { swap(v[1], v[3]); }
			tmp.emplace_back(v);
			xs.emplace_back(v[0]);
			xs.emplace_back(v[2]);
			ys.emplace_back(v[1]);
			ys.emplace_back(v[3]);
		}
		CDiscretize xCode(xs), yCode(ys);
		CDiff2<> diff(xCode.size() + 1, yCode.size() + 1);
		for (const auto& v : tmp) {
			diff.Set(xCode[v[0]], yCode[v[1]],xCode[v[2]], yCode[v[3]],1);
		}
		auto res = diff.Ans();
		C1097Int<> biRet;
		for (int r = 0; r+1 < diff.m_iR; r++) {			
			for (int c = 0; c+1 < diff.m_iC; c++) {				
				if (res[r][c] > 0) {
					C1097Int<> cur = ((long long)xCode.m_nums[r + 1] - xCode.m_nums[r]) * (yCode.m_nums[c + 1] - yCode.m_nums[c]);
					biRet += cur;
				}
			}
		}
		return biRet.ToInt();
	}
};

单元测试

template<class T1,class T2>
void AssertEx(const T1& t1, const T2& t2)
{
	Assert::AreEqual(t1 , t2);
}

template<class T>
void AssertEx(const vector<T>& v1, const vector<T>& v2)
{
	Assert::AreEqual(v1.size(), v2.size());	
	for (int i = 0; i < v1.size(); i++)
	{
		Assert::AreEqual(v1[i], v2[i]);
	}
}

template<class T>
void AssertV2(vector<vector<T>> vv1, vector<vector<T>> vv2)
{
	sort(vv1.begin(), vv1.end());
	sort(vv2.begin(), vv2.end());
	Assert::AreEqual(vv1.size(), vv2.size());
	for (int i = 0; i < vv1.size(); i++)
	{
		AssertEx(vv1[i], vv2[i]);
	}
}

namespace UnitTest
{
	vector<vector<int>> rectangles;
	TEST_CLASS(UnitTest)
	{
	public:
		TEST_METHOD(TestMethod0)
		{
			rectangles = { {0,0,2,2},{1,0,2,3},{1,0,3,1} };
			auto res = Solution().rectangleArea(rectangles);
			AssertEx( 6, res);
		}
		TEST_METHOD(TestMethod1)
		{
			rectangles = { {0,0,1000000000,1000000000} };
			auto res = Solution().rectangleArea(rectangles);
			AssertEx(49, res);
		}
		TEST_METHOD(TestMethod2)
		{
			rectangles = { {93516, 44895, 94753, 69358}, { 13141,52454,59740,71232 }, { 22877,11159,85255,61703 }, { 11917,8218,84490,36637 }, { 75914,29447,83941,64384 }, { 22490,71433,64258,74059 }, { 18433,51177,87595,98688 }, { 70854,80720,91838,92304 }, { 46522,49839,48550,94096 }, { 95435,37993,99139,49382 }, { 10618,696,33239,45957 }, { 18854,2818,57522,78807 }, { 61229,36593,76550,41271 }, { 99381,90692,99820,95125 } };
			auto res = Solution().rectangleArea(rectangles);
			AssertEx(971243962, 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.coloradmin.cn/o/1833643.html

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

相关文章

物联网协议基础知识

协议允许节点以结构化的方式在它们之间进行交互。由于物联网设备的需求和用例在过去几年中迅速发展&#xff0c;协议也随之发展。总而言之&#xff0c;主要有两类协议&#xff1a;网络协议和数据协议。此分类来自广泛应用于 IT 通信网络的 OSI&#xff08;开放系统互连&#xf…

深入探讨JavaScript的执行机制

预编译 首先下面这段代码的执行是一个怎样的结果呢&#xff1f; showName(); console.log(MyName);var MyName 小陈同学function showName() {console.log(函数showName被执行); }在这段代码中我们声明了一个变量MyName和一个函数showName&#xff0c;调用函数&#xff0c;打…

TWM论文阅读笔记

这是ICLR2023的一篇world model论文&#xff0c;用transformer来做世界模型的sequence prediction。文章贡献是transformer-based world model&#xff08;不同于以往的如transdreamer的world model&#xff0c;本文的transformer-based world model在inference 的时候可以丢掉…

手机usb共享网络电脑没反应的方法

适用于win10电脑&#xff0c;安卓手机上可以 开启usb网络共享选择&#xff0c;如果选择后一直跳&#xff0c;让重复选择usb选项的话&#xff0c;就开启 开发者模式&#xff0c;进到 开发者模式 里设置 默认usb 共享网络 选项 &#xff0c;就不会一直跳让你选。 1.先用数据线 连…

一款.NET开源、功能强大、跨平台的绘图库 - OxyPlot

前言 今天大姚给大家分享一款.NET开源&#xff08;MIT License&#xff09;、免费、跨平台、功能强大的绘图库&#xff0c;支持多平台使用&#xff08;包括&#xff1a;WPF、UWP、WinForm、Silverlight、Xamarin.iOS、Xamarin.Android、Xamarin.Forms 和 Xamarin.Mac等&#x…

Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors

Disk /dev/sda: 107.4 GB, 107374182400 bytes, 209715200 sectors 块设备名称为&#xff1a; /dev/sda 设备的大小为&#xff1a;107.4 GB 107374182400 bytes &#xff1a; 107374182400/1024/1024/1024100G &#xff08;1&#xff09;块设备名称为&#xff1a;/dev/sd…

DS18B20温度传感器完整使用介绍(配合51单片机)

DS18B20是一款由Maxim Integrated&#xff08;原Dallas Semiconductor&#xff09;生产的数字温度传感器&#xff0c;以其高精度、低功耗、灵活的接口方式和易于使用的特性&#xff0c;在各种温度监测应用中被广泛采用。 以下是DS18B20的详细介绍&#xff1a; 基本特性 数字输…

【CSS in Depth2精译】1.1 层叠

CSS 本质上就是声明规则&#xff0c;并让这些特定的规则在各种情况下生效。一个类添加到某个元素上&#xff0c;则应用这个类包含的这一些样式&#xff1b;元素 X 是元素 Y 的一个子节点&#xff0c;则应用另一些样式。浏览器于是根据这些规则&#xff0c;判定所有样式生效的具…

数据结构-十大排序算法集合(四万字精讲集合)

前言 1&#xff0c;数据结构排序篇章是一个大的工程&#xff0c;这里是一个总结篇章&#xff0c;配备动图和过程详解&#xff0c;从难到易逐步解析。 2&#xff0c;这里我们详细分析几个具备教学意义和实际使用意义的排序&#xff1a; 冒泡排序&#xff0c;选择排序&#xff0c…

解决安全规模问题:MinIO 企业对象存储密钥管理服务器

在强大可靠的存储解决方案领域&#xff0c;MinIO 作为持久层脱颖而出&#xff0c;为组织提供安全、持久和可扩展的存储选项。MinIO 通常负责处理关键任务数据&#xff0c;在确保高可用性方面发挥着至关重要的作用&#xff0c;有时甚至在全球范围内。存储数据的性质&#xff0c;…

vue音乐播放条

先看效果 再看代码 <template><div class"footer-player z-30 flex items-center p-2"><div v-if"isShow" class"h-12 w-60 overflow-hidden"><div :style"activeStyle" class"open-detail-control-wrap&…

《现代通信原理与技术》数字调制与解调(MSK调制)实验报告

摘 要&#xff1a; 本实验旨在研究数字调制中的最小频移键控&#xff08;MSK&#xff09;调制技术&#xff0c;并使用MATLAB软件对其进行模拟和实现。首先&#xff0c;我们介绍了MSK调制的原理和特点&#xff0c;以及其在数字通信系统中的应用。然后&#xff0c;我们使用MATLAB…

分布式光纤测温DTS使用的单模光纤与多模光纤有何区别?

分布式光纤测温DTS中使用的单模光纤和多模光纤之间存在着本质区别。单模光纤是一种在光纤通信中应用广泛的光纤类型&#xff0c;几乎所有的光纤入户和主干线通信都采用单模光纤。从通信的角度来看&#xff0c;单模光纤就好比一条单行道的高速铁路&#xff0c;而多模光纤则类似于…

微型操作系统内核源码详解系列五(2):cm3下栈的初始化

系列一&#xff1a;微型操作系统内核源码详解系列一&#xff1a;rtos内核源码概论篇&#xff08;以freertos为例&#xff09;-CSDN博客 系列二&#xff1a;微型操作系统内核源码详解系列二&#xff1a;数据结构和对象篇&#xff08;以freertos为例&#xff09;-CSDN博客 系列…

Flutter 实现软鼠标

文章目录 前言一、如何实现&#xff1f;1、记录鼠标偏移2、MouseRegion获取偏移3、Transform移动图标 二、完整代码三、使用示例总结 前言 flutter在嵌入式系统中运行时&#xff0c;有可能遇到drm鼠标无法使用的情况&#xff0c;但鼠标事件却可以正常接收&#xff0c;此时如果…

一季度直播6000场,同比增长60%,遥望科技透露重要信息

6月17日&#xff0c;经由深圳证券交易所许可&#xff0c;遥望科技&#xff08;股票代码&#xff1a;002291&#xff09;正式对《年报问询函》进行公开回复&#xff0c;就经营的多个维度做出解释和回应。 在回复中&#xff0c;遥望科技预测2024年毛利率为14.4%&#xff0c;相比…

MybatisPlus:高效便捷的Java持久层框架

一、MybatisPlus简介 MybatisPlus&#xff08;简称MP&#xff09;是一个流行的Java持久层框架&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生&#xff0c;旨在简化数据库操作和提高开发效率。MybatisPlus为开发者提供了一套方便的API和…

【Java开发规范】IDEA 设置 text file encoding 为 UTF-8,且文件的换行符使用 Unix 格式

1. IDEA 设置 text file encoding 为 UTF-8 file -> settings -> editor -> code style -> file encoding Transparent-native-to-asci conversion 要不要勾选&#xff1f;> 不推荐勾选&#xff08;它的作用是用来自动转换ASCII编码&#xff0c;防止文件乱码&am…

vue3的基本使用方法

【 vue3实例 】 【 0 】对象、方法和属性 对象&#xff08;Object&#xff09;&#xff1a; 对象是编程中的一个数据结构&#xff0c;它可以包含多种数据类型&#xff0c;包括数字、字符串、布尔值、数组、其他对象等。对象通常由一系列属性和方法组成。在面向对象编程&…

如何在纯内网环境下,将EasyCVR视频汇聚网关通过4G与第三方公网云平台级联?

EasyCVR视频汇聚网关是TSINGSEE青犀软硬一体的一款产品&#xff0c;可提供多协议的接入、音视频采集、处理&#xff0c;能实现海量前端设备的轻量化接入/转码/分发、视频直播、云端录像、云存储、检索回看、智能告警、平台级联等&#xff0c;兼容多种操作系统&#xff0c;轻松扩…