3072. 将元素分配到两个数组中 II Rust 线段树 + 离散化

news/2024/9/22 17:21:52/

题目

给你一个下标从 1 开始、长度为 n 的整数数组 nums

现定义函数 greaterCount ,使得 greaterCount(arr, val) 返回数组 arr 中 严格大于 val 的元素数量。

你需要使用 n 次操作,将 nums 的所有元素分配到两个数组 arr1arr2 中。在第一次操作中,将 nums[1] 追加到 arr1 。在第二次操作中,将 nums[2] 追加到 arr2 。之后,在第 i 次操作中:

如果 greaterCount(arr1, nums[i]) > greaterCount(arr2, nums[i]) ,将 nums[i] 追加到 arr1
如果 greaterCount(arr1, nums[i]) < greaterCount(arr2, nums[i]),将 nums[i] 追加到 arr2
如果 greaterCount(arr1, nums[i]) == greaterCount(arr2, nums[i]) ,将 nums[i] 追加到元素数量较少的数组中。
如果仍然相等,那么将 nums[i] 追加到 arr1
连接数组 arr1arr2 形成数组 result 。例如,如果 arr1 == [1,2,3]arr2 == [4,5,6] ,那么 result = [1,2,3,4,5,6]

返回整数数组 result

示例

示例 1

输入:nums = [2,1,3,3]
输出:[2,3,1,3]
解释:在前两次操作后,arr1 = [2] ,arr2 = [1] 。
在第 3 次操作中,两个数组中大于 3 的元素数量都是零,并且长度相等,因此,将 nums[3] 追加到 arr1 。
在第 4 次操作中,两个数组中大于 3 的元素数量都是零,但 arr2 的长度较小,因此,将 nums[4] 追加到 arr2 。
在 4 次操作后,arr1 = [2,3] ,arr2 = [1,3] 。
因此,连接形成的数组 result 是 [2,3,1,3] 。

示例 2

输入:nums = [5,14,3,1,2]
输出:[5,3,1,2,14]
解释:在前两次操作后,arr1 = [5] ,arr2 = [14] 。
在第 3 次操作中,两个数组中大于 3 的元素数量都是一,并且长度相等,因此,将 nums[3] 追加到 arr1 。
在第 4 次操作中,arr1 中大于 1 的元素数量大于 arr2 中的数量(2 > 1),因此,将 nums[4] 追加到 arr1 。
在第 5 次操作中,arr1 中大于 2 的元素数量大于 arr2 中的数量(2 > 1),因此,将 nums[5] 追加到 arr1 。
在 5 次操作后,arr1 = [5,3,1,2] ,arr2 = [14] 。
因此,连接形成的数组 result 是 [5,3,1,2,14] 。

示例 3

输入:nums = [3,3,3,3]
输出:[3,3,3,3]
解释:在 4 次操作后,arr1 = [3,3] ,arr2 = [3,3] 。
因此,连接形成的数组 result 是 [3,3,3,3] 。

提示:

3 <= n <= 105
1 <= nums[i] <= 109

思路

离散化 + 线段树,由于基础的线段树可以AC,不再使用懒标记去优化。

AC代码

rust">use std::collections::HashMap;struct Tree{tree: Vec<i32>
}impl Tree {pub fn new(len: usize) -> Self {Tree {tree: vec![0; len]}}/*** 更新**/pub fn update(&mut self, node: usize, sign_idx: usize, l: usize, r: usize) {if l == r {self.tree[node] += 1;return;}let mid: usize = l + r >> 1;let l_node: usize = (node << 1) + 1;let r_node: usize = l_node + 1;if sign_idx <= mid {self.update(l_node, sign_idx, l, mid);} else {self.update(r_node, sign_idx, mid + 1, r);}self.tree[node] = self.tree[l_node] + self.tree[r_node];}/*** 查询**/pub fn query(&mut self, node: usize, l: usize, r: usize, start: usize, end: usize) -> i32 {if l > end || r < start {return 0;}if l >= start && r <= end {return self.tree[node];}let mid: usize = l + r >> 1;let l_node: usize = (node << 1) + 1;let r_node: usize = l_node + 1;self.query(l_node, l, mid, start, end) + self.query(r_node, mid + 1, r, start, end)}
}impl Solution {pub fn result_array(v: Vec<i32>) -> Vec<i32> {let len: usize = v.len();let tree_len: usize = len << 2;let mut tree1: Tree = Tree::new(tree_len);let mut tree2: Tree = Tree::new(tree_len);let mut arr1: Vec<i32> = vec![v[0]];let mut arr2: Vec<i32> = vec![v[1]];let mut mp: HashMap<usize, usize> = HashMap::new();let mut cp_v: Vec<i32> = v.clone();cp_v.sort();for (idx, tem) in cp_v.iter().enumerate() {mp.insert(*tem as usize, idx);}if let Some(tem_val) = mp.get(&(v[0] as usize)) {tree1.update(0, *tem_val, 0, len - 1);}if let Some(tem_val) = mp.get(&(v[1] as usize)) {tree2.update(0, *tem_val, 0, len - 1);}for idx in 2 .. len {let val: i32 = v[idx];let mut mp_val: usize = 0;if let Some(tem_val) = mp.get(&(val as usize)) {mp_val = *tem_val;}            let s1: i32 = tree1.query(0, 0, len - 1, mp_val + 1, len - 1);let s2: i32 = tree2.query(0, 0, len - 1, mp_val + 1, len - 1);if s1 > s2 {arr1.push(val);tree1.update(0, mp_val, 0, len - 1);continue;}if s2 > s1 {arr2.push(val);tree2.update(0, mp_val, 0, len - 1);continue;}let len1: usize =  arr1.len();let len2: usize = arr2.len();if len1 <= len2 {arr1.push(val);tree1.update(0, mp_val, 0, len - 1);} else {arr2.push(val);tree2.update(0, mp_val, 0, len - 1);}}arr1.extend(arr2);arr1}
}


http://www.ppmy.cn/news/1467187.html

相关文章

Redis的哨兵模式

什么是哨兵模式 Redis的哨兵模式&#xff08; Sentinel mode &#xff09;是⼀个⾼可⽤解决⽅案&#xff0c;当运⾏多个 Redis 实例并且需要⾃动故障转移时&#xff0c;哨兵模式⾮常有⽤。 在⼀个典型的哨兵模式下&#xff0c;⾄少需要3 个哨兵实例来避免 “ 脑裂 ” &#xff…

将现有web项目打包成electron桌面端教程(一)vue3+vite+js版

后续项目需要web端和桌面端&#xff0c;为了提高开发效率&#xff0c;准备直接将web端的代码打包成桌面端&#xff0c;在此提前记录一下demo打包的过程&#xff0c;需要注意的是vue2或者vue3vitets或者vue-cli的打包方式各不同&#xff0c;如果你的项目不是vue3vitejs&#xff…

【Redis延迟队列】redis中的阻塞队列和延迟队列

阻塞队列&#xff08;RBlockingQueue&#xff09; 作用和特点&#xff1a; 实时性&#xff1a;阻塞队列用于实时处理消息。生产者将消息放入队列&#xff0c;消费者可以立即从队列中取出并处理消息。阻塞特性&#xff1a;如果队列为空&#xff0c;消费者在尝试获取消息时会被…

【网络通信层】华为云连接MQTT设备

本文介绍华为云设备连接到设备的操作。 目录 一、在华为云创建设备 二、连接MQTT 三、通信 一、在华为云创建设备 现在华为云上可以免费使用部分受限服务&#xff0c;包括免费创建自己的设备连接。 首先&#xff0c;登录华为云平台共建智能世界云底座-华为云 (huaweicl…

Ollama+FastAPI+React手把手构建自己的本地大模型,支持SSE

最近大家都在玩LLM&#xff0c;我也凑了热闹&#xff0c;简单实现了一个本地LLM应用&#xff0c;分享给大家&#xff0c;百分百可以用哦&#xff5e;^ - ^ 先介绍下我使用的三种工具&#xff1a; Ollama&#xff1a;一个免费的开源框架&#xff0c;可以让大模型很容易的运行在…

Thread线程控制之sleep、join、setDaemon方法的用处

Thread线程控制之sleep、join、setDaemon方法的用处 sleep方法 public static void sleep(long millis) throws InterruptedException使当前正在执行的线程以指定的毫秒数暂停&#xff08;暂时停止执行&#xff09;&#xff0c;具体取决于系统定时器和调度程序的精度和准确性…

20232815 2023-2024-2 《网络攻防实践》实践十一报告

20232815 2023-2024-2 《网络攻防实践》实践十一报告 1.实践内容 网络渗透&#xff1a; 网络渗透是攻击者常用的一种攻击手段&#xff0c;也是一种综合的高级攻击技术&#xff0c;同时网络渗透也是安全工作者所研究的一个课题&#xff0c;在他们口中通常被称为”渗透测试&…

数据结构:双链表

数据结构&#xff1a;双链表 题目描述参考代码 题目描述 输入样例 10 R 7 D 1 L 3 IL 2 10 D 3 IL 2 7 L 8 R 9 IL 4 7 IR 2 2输出样例 8 7 7 3 2 9参考代码 #include <iostream>using namespace std;const int N 100010;int m; int idx, e[N], l[N], r[N];void init…