力扣(leetcode)每日一题 2286 以组为单位订音乐会的门票 | 线段树

news2024/11/19 12:37:35

2286. 以组为单位订音乐会的门票

题干

一个音乐会总共有 n 排座位,编号从 0n - 1 ,每一排有 m 个座椅,编号为 0m - 1 。你需要设计一个买票系统,针对以下情况进行座位安排:

  • 同一组的 k 位观众坐在 同一排座位,且座位连续
  • k 位观众中 每一位 都有座位坐,但他们 不一定 坐在一起。

由于观众非常挑剔,所以:

  • 只有当一个组里所有成员座位的排数都 小于等于 maxRow ,这个组才能订座位。每一组的 maxRow 可能 不同
  • 如果有多排座位可以选择,优先选择 最小 的排数。如果同一排中有多个座位可以坐,优先选择号码 最小 的。

请你实现 BookMyShow 类:

  • BookMyShow(int n, int m) ,初始化对象,n 是排数,m 是每一排的座位数。
  • int[] gather(int k, int maxRow) 返回长度为 2 的数组,表示 k 个成员中 第一个座位 的排数和座位编号,这 k 位成员必须坐在 同一排座位,且座位连续 。换言之,返回最小可能的 rc 满足第 r 排中 [c, c + k - 1] 的座位都是空的,且 r <= maxRow 。如果 无法 安排座位,返回 []
  • boolean scatter(int k, int maxRow) 如果组里所有 k 个成员 不一定 要坐在一起的前提下,都能在第 0 排到第 maxRow 排之间找到座位,那么请返回 true 。这种情况下,每个成员都优先找排数 最小 ,然后是座位编号最小的座位。如果不能安排所有 k 个成员的座位,请返回 false

示例 1:

输入:
[“BookMyShow”, “gather”, “gather”, “scatter”, “scatter”]
[[2, 5], [4, 0], [2, 0], [5, 1], [5, 1]]
输出:
[null, [0, 0], [], true, false]

解释:
BookMyShow bms = new BookMyShow(2, 5); // 总共有 2 排,每排 5 个座位。
bms.gather(4, 0); // 返回 [0, 0]
// 这一组安排第 0 排 [0, 3] 的座位。
bms.gather(2, 0); // 返回 []
// 第 0 排只剩下 1 个座位。
// 所以无法安排 2 个连续座位。
bms.scatter(5, 1); // 返回 True
// 这一组安排第 0 排第 4 个座位和第 1 排 [0, 3] 的座位。
bms.scatter(5, 1); // 返回 False
// 总共只剩下 1 个座位。

提示:

  • 1 <= n <= 5 * 104
  • 1 <= m, k <= 109
  • 0 <= maxRow <= n - 1
  • gatherscatter 调用次数不超过 5 * 104 次。
题解1

这里实现的时候,我还不会线段树。硬是通过小优化使得提交通过

在这里插入图片描述

class BookMyShow {
     int totalRow;
    int[] arr;
    int jump = 0;
    long totalCount;

    public BookMyShow (int n, int m) {
        // 需要加快更新的频率
        arr = new int[n];
        totalRow = m;
        totalCount = (long) n * m;
    }

    public int[] gather(int k, int maxRow) {
        // 快速失败
        if (k > totalRow) {
            return new int[0];
        }

        for (int i = jump; i <= maxRow; i++) {
            // 计算是否放得下
            if (arr[i] + k <= totalRow) {
                int[] res = new int[]{i, arr[i]};
                arr[i] = arr[i] + k;
                // 没有问题
                totalCount -= k;
                return res;
            }
        }
        return new int[0];
    }

    public boolean scatter(int k, int maxRow) {
        if (totalCount < k) {
            return false;
        }
        int count = 0;
        boolean flag = false;
        int index = 0;
        for (int i = jump; i <= maxRow; i++) {
            count += totalRow - arr[i];
            if (count >= k) {
                flag = true;
                index = i;
                break;
            }
        }
        if (!flag) {
            return false;
        }
        // 可以省略
//        for (int i = jump; i < index; i++) {
//            arr[i] = totalRow;
//        }
        jump = index;
        // 多累计了3人,需要减去
        arr[index] = totalRow - (count - k);
        totalCount -= k;
        return true;
    }
}

题解2

这里的线段树应该不是最优解,不然这里的数值不会这么难看
但是我没有精力去精进
因为用前面题解的模板来改写
在这里插入图片描述

class Solution2286 {  
    public static void main(String[] args) {  
        BookMyShow bookMyShow = new BookMyShow(5, 9); // 假设是9个位置  
        bookMyShow.scatter(9, 1);  
        bookMyShow.scatter(1, 3);  
        bookMyShow.gather(3, 4);  
        bookMyShow.gather(1, 1);  
        bookMyShow.gather(10, 4);  
    }  
  
    static class BookMyShow {  
        int totalSpace;  
        int[] arr;  
        long[] sumArr;  
        int[] minArr;  
        int right;  
        int left = 1;  
        int root = 1;  
  
        public BookMyShow(int n, int m) {  
            right = n;  
            int length = n + 1;  
            arr = new int[length];  
            sumArr = new long[4 * length]; // 这里加速了范围上累加和的查询  
            minArr = new int[4 * length];  // 这里加速了范围上最小值的查询  
            totalSpace = m;  
        }  
  
  
        public int[] gather(int k, int maxRow) {  
            maxRow++;  
            int min = getMin(left, right, root, totalSpace - k);//  9 个位置 来了5个  需要找小于等于4的  
            if (min > maxRow) {  
                return new int[0];  
            }  
            // 查询当前min的值  
            long query = query(min, min);  
            // 更新当前min的值  
            update(min, min, (int) query + k);  
            return new int[]{min - 1, (int) query};  
        }  
  
        //  9871    9   只要找到小于9的行就可以进行增加了  
        public boolean scatter(int k, int maxRow) {  
            maxRow++;  
            // 计算和  
            long res = query(1, maxRow);  
            // 当这里的累计大于k的时候就可以入座  
            if (res + k > (long) (maxRow) * totalSpace) {  
                return false;  
            }  
            //  9 个位置 只要是小于9的就可以了,查询小于等于8的  
            int min = getMin(left, right, root, totalSpace - 1);  
            while (true) {  
                int query = (int) query(min, min);  
                if (query + k <= totalSpace) { // 当前排的位置可以把人安排了就安排入座  
                    update(min, min, k + query); // 这里需要k+min  
                    return true;  
                }  
                // 更新  
                update(min, min, totalSpace);  
                k -= (totalSpace - query);// 这里查询到4个,那么可以安排 5个入座。计算就是9-4  
                min = getMin(left, right, root, totalSpace - 1);  
            }  
        }  
  
        public int getMin(int left, int right, int node, int value) {  
            if (left == right) {  
                if (minArr[node] > value) {  
                    // 没有  
                    return Integer.MAX_VALUE;  
                }  
                return left;  
            }  
            int mid = (left + right) / 2;  
            if (minArr[node * 2] <= value) {  
                return getMin(left, mid, node * 2, value);  
            } else {  
                return getMin(mid + 1, right, node * 2 + 1, value);  
            }  
        }  
  
        public long query(int start, int end) {  
            return query(start, end, left, right, root);  
        }  
  
        public long query(int start, int end, int left, int right, int node) {  
            if (start <= left && right <= end) {  
                return sumArr[node];  
            }  
            int mid = (left + right) / 2;  
            long total = 0;  
            if (start <= mid) { // 下发左边  
                total += query(start, end, left, mid, node * 2);  
            }  
            if (end > mid) { // 下发右边  
                total += query(start, end, mid + 1, right, node * 2 + 1);  
            }  
            return total;  
        }  
  
        public void update(int start, int end, int value) {  
            update(start, end, value, left, right, root);  
        }  
  

		// 模板是范围上更新,但是这里的实际情况是单点更新
        public void update(int start, int end, int value, int left, int right, int node) {  
            if (start <= left && right <= end) {  
                sumArr[node] = value;  
                minArr[node] = value;  
                return;  
            }  
            int mid = (left + right) / 2;  
            if (start <= mid) { // 下发左边  
                update(start, end, value, left, mid, node * 2);  
            }  
            if (end > mid) { // 下发右边  
                update(start, end, value, mid + 1, right, node * 2 + 1);  
            }  
            // 刷新求和  
            sumArr[node] = sumArr[node * 2] + sumArr[node * 2 + 1];  
            // 刷新最小  
            minArr[node] = Math.min(minArr[node * 2], minArr[node * 2 + 1]);  
        }  
  
    }  
  
}
总结

minArr的使用是超出了模板的范围

// 刷新求和  
sumArr[node] = sumArr[node * 2] + sumArr[node * 2 + 1];  
// 刷新最小  
minArr[node] = Math.min(minArr[node * 2], minArr[node * 2 + 1]);  

这些值的刷新,在递归前,还是递归后,还是递归方法的尽头。都是有讲究的

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

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

相关文章

物联网实训室建设的必要性

物联网实训室建设的必要性 一、物联网发展的背景 物联网&#xff08;IoT&#xff09;是指通过信息传感设备&#xff0c;按照约定的协议&#xff0c;将任何物品与互联网连接起来&#xff0c;进行信息交换和通信&#xff0c;以实现智能化识别、定位、跟踪、监控和管理的一种网络…

c语言实例 068

大家好&#xff0c;欢迎来到无限大的频道 今天给大家带来的是c语言。 题目描述 创建一个单链表&#xff0c;进行存储数据并且打印 创建一个单链表的基本步骤包括定义链表节点的结构体、实现插入数据的功能&#xff0c;以及打印链表的内容。以下是一个简单的C语言示例&#…

QT将QBytearray的data()指针赋值给结构体指针变量后数据不正确的问题

1、问题代码 #include <QCoreApplication>#pragma pack(push, 1) typedef struct {int a; // 4字节float b; // 4字节char c; // 1字节int *d; // 8字节 }testStruct; #pragma pack(pop)#include <QByteArray> #include <QDebug>int main() {testStruct …

【C++前缀和 数论 贪心】2245. 转角路径的乘积中最多能有几个尾随零|2036

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 质数、最大公约数、菲蜀定理 贪心&#xff08;决策包容性) LeetCode2245. 转角路径的乘积中最多能有几个尾随零 给你一个二维整数数组 grid &#xff0c;大小为 m x …

【有啥问啥】二分图(Bipartite Graph)算法原理详解

二分图&#xff08;Bipartite Graph&#xff09;算法原理详解 引言 二分图&#xff08;Bipartite Graph&#xff09;&#xff0c;又称二部图&#xff0c;是图论中的一个重要概念。在实际应用中&#xff0c;二分图模型经常用于解决如匹配问题、覆盖问题和独立集问题等。本文将…

实验2思科网院项目2.7.2-packet-tracer---configure-single-area-ospfv2---实践练习

实践练习 2.7.2-packet-tracer---configure-single-area-ospfv2---实践练习physical-mode 实验拓扑 相关设备配置 实验目标: 第 1 部分&#xff1a;构建网络并配置设备的基本设置 第 2 部分&#xff1a;配置和验证单区域 OSPFv2 的基本部署 第 3 部分&#xff1a;优化和验…

【STM32】 TCP/IP通信协议(3)--LwIP网络接口

LwIP协议栈支持多种不同的网络接口&#xff08;网卡&#xff09;&#xff0c;由于网卡是直接跟硬件平台打交道&#xff0c;硬件不同则处理也是不同。那Iwip如何兼容这些不同的网卡呢&#xff1f; LwIP提供统一的接口&#xff0c;底层函数需要用户自行完成&#xff0c;例如网卡的…

动态时钟控件:Qt/C++ 项目代码解读

基于Qt的动态时钟控件项目。该项目展示了如何通过Qt的绘图系统绘制一个带有表盘背景、时针、分针、秒针、以及时间日期显示的时钟。同时&#xff0c;这个时钟控件支持背景切换&#xff0c;并且每秒钟刷新一次&#xff0c;实时显示当前时间。 项目结构与功能概述 该时钟控件主…

Redis接口访问优化

说明&#xff1a;之前写过一篇使用Redis接口访问的博客&#xff0c;如下。最近有相关需求&#xff0c;把代码拿出来后&#xff0c;做了一些优化&#xff0c;挺有意思的&#xff0c;本文介绍在原基础上 使用Redis实现接口防抖 优化 总的来说&#xff0c;这次使用Redis实现接口…

自动驾驶汽车横向控制方法研究综述

【摘要】 为实现精确、稳定的横向控制&#xff0c;提高车辆自主行驶的安全性和保障乘坐舒适性&#xff0c;综述了近年来自动驾驶汽车横向控制方法的最新进展&#xff0c;包括经典控制方法和基于深度学习的方法&#xff0c;讨论了各类方法的性能特点及在应用中的优缺点&#xff…

【初阶数据结构】详解插入排序 希尔排序(内含排序的概念和意义)

文章目录 前言1. 排序的概念及其应用1.1 排序的概念1.2 排序的应用 2. 插入排序2.1 基本思想2.2 插入排序的代码实现2.3 插入排序算法总结 3. 希尔排序3.1 基本思想3.2 希尔排序的代码实现3.3 希尔排序的特征总结 前言 初级数据结构系列已经进入到了排序的部分了。相信大家听到…

计算机毕业设计 服装生产信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

记录|Modbus-TCP产品使用记录【德克威尔】

目录 前言一、德克威尔1.1 实验图1.2 DECOWELL IO Tester 软件1.3 读写设置1.4 C#进行Modbus-TCP读写 更新时间 前言 参考文章&#xff1a; 使用的第二款Modbus-TCP产品。 一、德克威尔 1.1 实验图 1.2 DECOWELL IO Tester 软件 这也是自带模块配置软件的。下图就是德克威尔的…

“Xian”(籼)和“Geng”(粳)米怎么读?

2018年&#xff0c;《自然》上刊登了一篇有关亚洲栽培稻基因组变异的重磅论文。研究成果本身自然引人关注&#xff0c;但更引人关注的是&#xff0c;这篇论文首次提出以“Xian”&#xff08;籼&#xff09;和“Geng”&#xff08;粳&#xff09;两个汉语农业术语代替Indica和Ja…

yum使用阿里云的镜像源报错 Failed connect to mirrors.aliyuncs.com:80; Connection refused“

报错&#xff1a;Failed connect to mirrors.aliyuncs.com:80; Connection refused"&#xff0c;如果单独只是这个报错的话&#xff0c;那么原因是由于非阿里云ECS用户无法解析主机“mirrors.cloud.aliyuncs.com”。如果不单单只是这个报错另外还有其它报错请参考我其它文…

Threejs创建正多边体

上一章节实现了球体的绘制&#xff0c;这节来绘制多面体&#xff0c;包括正多面体&#xff0c;平面中&#xff0c;每条边一样长组成的图形叫正多边形&#xff0c;这里每个面一样&#xff0c;叫正多面体。如上文一样&#xff0c;先要创建出基础的组件&#xff0c;包括场景&#…

C++基础---类和对象(上)

1.类的定义 C程序设计允许程序员使用类&#xff08;class&#xff09;定义特定程序中的数据类型。这些数据类型的实例被称为对象 &#xff0c;这些实例可以包含程序员定义的成员变量、常量、成员函数&#xff0c;以及重载的运算符。语法上&#xff0c;类似C中结构体&#xff0…

【机器学习】任务六:分类算法(支持向量机(SVM)在线性可分与不可分数据中的应用与可视化分析)

目录 1.知识简介 2.SVM 支持向量机模型训练与可视化报告 2.1 导入本项目所需的模块和包 &#xff08;1&#xff09;目的 &#xff08;2&#xff09;代码实现 &#xff08;3&#xff09;代码解释 2.2 随机生成线性可分的数据并可视化 &#xff08;1&#xff09;目的 &a…

[数据集][目标检测]电力场景防震锤缺陷检测数据集VOC+YOLO格式705张1类别

重要说明&#xff1a;防震锤缺陷图片太难找&#xff0c;数据集里面存在大量单一场景图片&#xff0c;请仔细查看图片预览谨慎下载&#xff0c;此外数据集均为小目标检测&#xff0c;如果训练map偏低属于正常现象 数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径…

特殊的 BASE64 1

这个一看题目就是base64编码表被改了. 知识点&#xff1a; Base64编码使用一个包含64个字符的字符集&#xff0c;这些字符分别是&#xff1a; 大写字母A-Z小写字母a-z数字0-9特殊字符和/ 这些字符分别对应64个不同的6位二进制数。在补零后形成的8位字节中&#xff0c;实际使用…