2022-10-09:我们给出了一个(轴对齐的)二维矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐
2022-10-09:我们给出了一个(轴对齐的)二维矩形列表 rectangles 。
对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标
(xi1, yi1) 是该矩形 左下角 的坐标, (xi2, yi2) 是该矩形 右上角 的坐标。
计算平面中所有 rectangles 所覆盖的 总面积 。
任何被两个或多个矩形覆盖的区域应只计算 一次 。
返回 总面积 。因为答案可能太大,返回 10^9 + 7 的 模 。
输入:rectangles = [[0,0,2,2],[1,0,2,3],[1,0,3,1]]。
输出:6。
答案2022-10-09:
线段树模板题。一个矩形两个事件。这道题用了树结构,对于rust有点复杂,用了Rc<RefCell>的数据类型。
力扣850上测试,rust语言占用内存最低,go语言占用内存略高于rust,但运行速度最快。
不管怎么说,rust和go都是要优于java的。用java的人们,你们赶紧换语言,java过时了。
java,go,rust运行情况见截图。
代码用rust编写。代码如下:
use std::cell::RefCell;
use std::iter::repeat;
use std::rc::Rc;
impl Solution {
pub fn rectangle_area(rectangles: Vec<Vec<i32>>) -> i32 {
let n = rectangles.len() as i32;
let mut arr: Vec<Vec<i64>> = repeat(repeat(0).take(4).collect())
.take((n << 1) as usize)
.collect();
let mut max: i64 = 0;
for i in 0..n {
// x1 y1 左下角点的坐标
// x2 y2 右上角点的坐标
// 解释一下y1为啥要+1
// 比如y1 = 3, y2 = 7
// 实际的处理的时候,真实的线段认为是闭区间[4,7]的
// 如果不这么处理会有问题
// 比如先在y1 = 3, y2 = 7上,都+1
// 那么此时:
// value: 0 0 1 1 1 1 1 0
// index: 1 2 3 4 5 6 7 8
// 这是不对的!
// 因为线段[3,7]长度是4啊!而在线段树里,是5个1!
// 所以,y1 = 3, y2 = 7
// 我们就是认为是4~7,都+1
// 那么此时:
// value: 0 0 0 1 1 1 1 0
// index: 1 2 3 4 5 6 7 8
// 线段树上,正好4个1,和我们想要的距离是一致的
let x1 = rectangles[i as usize][0];
let y1 = rectangles[i as usize][1] + 1;
let x2 = rectangles[i as usize][2];
let y2 = rectangles[i as usize][3];
arr[i as usize][0] = x1 as i64;
arr[i as usize][1] = y1 as i64;
arr[i as usize][2] = y2 as i64;
arr[i as usize][3] = 1;
arr[(i + n) as usize][0] = x2 as i64;
arr[(i + n) as usize][1] = y1 as i64;
arr[(i + n) as usize][2] = y2 as i64;
arr[(i + n) as usize][3] = -1;
max = get_max(max, y2 as i64);
}
return cover_area(&mut arr, n << 1, max);
}
}
fn get_max<T: Clone + Copy + std::cmp::PartialOrd>(a: T, b: T) -> T {
if a > b {
a
} else {
b
}
}
fn cover_area(arr: &mut Vec<Vec<i64>>, n: i32, max: i64) -> i32 {
// 所有的事件,都在arr里
// [x, y1, y2, +1/-1]
// 早 -> 晚
//Arrays.sort(arr, 0, n, (a, b) -> a[0] <= b[0] ? -1 : 1);
arr[0..n as usize].sort_by(|a, b| {
if a[0] < b[0] {
std::cmp::Ordering::Less
} else {
std::cmp::Ordering::Greater
}
});
// max y的值,可能的最大值,非常大也支持!
let mut dst = DynamicSegmentTree::new(max);
let mut pre_x: i64 = 0;
let mut ans: i64 = 0;
for i in 0..n {
// dst.query() : 开点线段树告诉你!y方向真实的长度!
ans += dst.query() * (arr[i as usize][0] - pre_x);
ans %= 1000000007;
pre_x = arr[i as usize][0];
dst.add(arr[i as usize][1], arr[i as usize][2], arr[i as usize][3]);
}
return ans as i32;
}
struct Node {
cover: i64,
len: i64,
left: Option<Rc<RefCell<Node>>>,
right: Option<Rc<RefCell<Node>>>,
}
impl Node {
fn new() -> Self {
Self {
cover: 0,
len: 0,
left: Option::None,
right: Option::None,
}
}
}
struct DynamicSegmentTree {
root: Rc<RefCell<Node>>,
size: i64,
}
impl DynamicSegmentTree {
fn new(max: i64) -> Self {
Self {
root: Rc::new(RefCell::new(Node::new())),
size: max,
}
}
pub fn add(&mut self, ll: i64, rr: i64, cover: i64) {
self.add0(Rc::clone(&self.root), 1, self.size, ll, rr, cover);
}
fn add0(&mut self, cur: Rc<RefCell<Node>>, l: i64, r: i64, ll: i64, rr: i64, cover: i64) {
if ll <= l && rr >= r {
cur.as_ref().borrow_mut().cover += cover;
} else {
if cur.as_ref().borrow().left.is_none() {
cur.as_ref().borrow_mut().left = Some(Rc::new(RefCell::new(Node::new())));
}
if cur.as_ref().borrow().right.is_none() {
cur.as_ref().borrow_mut().right = Some(Rc::new(RefCell::new(Node::new())));
}
let m: i64 = l + ((r - l) >> 1);
if ll <= m {
self.add0(
Rc::clone(&cur.as_ref().borrow().left.as_ref().unwrap()),
l,
m,
ll,
rr,
cover,
);
}
if rr > m {
self.add0(
Rc::clone(&cur.as_ref().borrow().right.as_ref().unwrap()),
m + 1,
r,
ll,
rr,
cover,
);
}
}
self.push_up(cur, l, r);
}
fn push_up(&mut self, cur: Rc<RefCell<Node>>, l: i64, r: i64) {
if cur.as_ref().borrow().cover > 0 {
cur.as_ref().borrow_mut().len = r - l + 1;
} else {
cur.as_ref().borrow_mut().len = if !cur.as_ref().borrow().left.is_none() {
cur.as_ref()
.borrow_mut()
.left
.as_mut()
.unwrap()
.as_ref()
.borrow()
.len
} else {
0
} + if !cur.as_ref().borrow().right.is_none() {
cur.as_ref()
.borrow_mut()
.right
.as_mut()
.unwrap()
.as_ref()
.borrow()
.len
} else {
0
};
}
}
pub fn query(&mut self) -> i64 {
return self.root.as_ref().borrow().len;
}
}
fn main() {
let rectangles = vec![vec![0, 0, 2, 2], vec![1, 0, 2, 3], vec![1, 0, 3, 1]];
let ans = Solution::rectangle_area(rectangles);
println!("ans = {:?}", ans);
}
struct Solution {}
执行结果如下:


2022-10-09:我们给出了一个(轴对齐的)二维矩形列表 rectangles 。 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐的更多相关文章
- 用Python+qrcode库创建一个包含信息的二维码
安装qrcode库和PIL库 在命令行中分别输入pip install qrcode 和pip install pillow 导入库格式如下: import PIL import qrcode 下面以 ...
- 一个不错的PHP二维数组排序函数简单易用存用
一个不错的PHP二维数组排序函数简单易用存用 传入数组,传入排序的键,传入排序顺序 public function array_sort($arr,$keys,$type='asc') { $keys ...
- 旋转图像 给定一个 n × n 的二维矩阵表示一个图像。
给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像. 示例 : 给定 ma ...
- 小程序踩过的一个小坑---解析二维码decodeURIComponent() url解码
因为我们需要用户扫码进入小程序,每一个货柜都有一个对应的二维码,当然每个二维码里的信息也不一样.用户扫码进入小程序之后,二维码的信息会以参数q带进去,而我们只能在onLoad事件中拿到这个参数, 但是 ...
- Anaconda+django写出第一个web app(二)
今天开始建立App中的第一个Model,命名为Tutorial. Model的定义在main文件夹下的models.py中通过类进行,我们希望Tutorial这个model包含三个属性:标题.内容和发 ...
- 存在一个足够大的二维数组,每个数组中的值都是整数,使用javascript如何实现按每个数组中的平均值,从大到小排序这个二维数组?
这是牛客网上的一道题~ 题意:对数组排序,顺序是按照数组的平均值,即按照一个元素和平均值相减的绝对值的大小来排序...本例按这个绝对值递增排序 解题思想:先求出这个数组的平均值,如果 a<b,那 ...
- 一个for循环打印二维数组
#include<stdio.h> #define MAXX 2 #define MAXY 3 void printarray() { ,,,,,}; ;i< MAXX*MAXY;i ...
- 一个有用的排序函数,array_multisort(),下面的一个用法是根据二维数组里的一个字段值的大小,对该二维数组进行重新排序
从二维数组$cashes中取出一列 'store_id'(二维数组中的每个一维数组都有的字段),按照这个的大小排序,对二维数组$caches里面的一维数组进行重新排序 实际应用如下 想让相同部门的排在 ...
- poj2155一个二维树状数组
...
- 我写的一个Qt 显示二维码( QR Code)的控件(可以去掉对 libpthread 的依赖,而且编译出的库文件可以在 vc2010 的release 模式下使用)
最近一个项目需要显示二维码,所以花了点时间(只用了一个晚上,写的很不完善),写了个显示二维码的控件.当然这个控件用到了些开源的代码,比如qrencode,所以我也打算把我的代码开源. 我的代码参考了 ...
随机推荐
- Vue的官方脚手架 Vue-cli 安装使用解析
------------恢复内容开始------------ 1.首先什么是vue-cli 可以知道Vue-cli是一个官方提供的脚手架,主要作用是用来快速搭建Vue的项目模板,可以预先定义好项目的结 ...
- mfc edit只允许输入数字
1.给EDIT控件添加 EN_CHANGE 事件 2.事件中的代码如下: 1 CString strEditVidoe; 2 GetDlgItem( iId )->GetWindowText( ...
- 关于Go语言的底层,你想知道的都在这里!
目录 1. GoLang语言 1.1 Slice 1.2 Map 1.3 Channel 1.4 Goroutine 1.5 GMP调度 1.6 垃圾回收机制 1.7 其他知识点 2. Web框架Gi ...
- OVS学习博客推荐
博客学习 大致看一遍 openvswitch处理upcall过程分析 upcall-cost分析 连接跟踪(conntrack):原理.应用及 Linux 内核实现 ovs upcall处理流程 Li ...
- [Python]语音识别媒体中的音频到文本
@ 目录 准备工作 视频转音频 识别音频到文本 音频直接转换文本 准备工作 安装python3环境 申请一个可用的语音转换API,此篇以Microsoft Azure Speech为例 在Micros ...
- conda环境下使用nvcc -V报错nvcc: command not found的一种解决方法
前言 缘起 实验室的学弟问我为什么他使用nvcc命令报错,起先我以为他用的是老师给的root账户,按照参考文献1便可以解决问题. 但由于并非root用户,/usr/local下没有cuda,于是便 ...
- SpringBoot——数据访问
对于数据访问层,无论是 SQL 还是 NoSQL,SpringBoot 默认采用整合 Spring Data 的方式进行统一处理,添加大量自动配置,屏蔽了很多设置.引入各种 xxxTemplate,x ...
- java多线程基础小白指南--关键字识别(start,run,sleep,wait,join,yield)
在学习java多线程基础上,会遇到几个关键字,理解并识别它们是掌握多线程的必备知识,下面,我将通过源码或者程序演示给出我对这几个关键字的理解,如果有不同意见,欢迎在评论区或者发私信与我探讨. 一.st ...
- Redis分布式Session和普通的cookie session有什么区别?
Redis 是一种高性能的缓存和 key-value 存储系统,常被用来实现分布式 Session 的方案.在这种方案中,用户的登录信息存储在 Redis 中,而不是存储在本地的 cookie 或 s ...
- ACM-学习记录-DP-1
DPL_1_A: Coin Changing Problem 每次均有两种选择,即选择当前的,即为在当前状态+1,否则维持原来的T[j+d[i]] #include<iostream> # ...