【练习题】数据离散化+二维前缀和

news2024/10/6 18:25:03

【练习题】数据离散化+二维前缀和

    • 题目大意
      • 输入
      • 输出
      • 样例解释
      • 重要提示
    • 思路
      • 代码
      • 时间复杂度

题目大意

mtc是一个很优秀的同学,他学习认真,经常刷题。这天,他正好学习到了数据离散化与二位前缀和的相关概念,并给大家进行科普.
数据的离散化:有些教据本身很大,自身无法作为数组的下标保存对应的属性,如果这时只是需要这堆数据的相对属性,那么可以对其进行离散化处理。当数据只与它们之间的相对大小有关,而与具体是多少无关时,可以进行离散化。百度百科
例如:设有4个数:
1234567、123456789、12345678、123456
排序:123456<1234567<12345678<123456789
=>1<2<3<4
那么这4个数可以表示成:2、4、3、1
实现离散化的方法有很多,大家可以自行学习
二维前缀和:定义一个二维数组s0,s川们表示二维数组中,左上角(1,1)到右下角,所包围的矩阵元素的和。如下图所示
在这里插入图片描述
在这里插入图片描述
二维前缀和的推导公式:整个外围蓝色矩形面积s们=绿色面积S - 1]M] + 紫色面积 -1重复加的红色的面积 - 1-1]+小方块的面积a[ilij]。
使用二位前缀和求解矩阵的面积:求以(x1,y1)为左上角和以(2,y2)为右下角的矩阵的元素的和。
在这里插入图片描述
绿色形的面积 S= 整个外围面积[x2,2] -黄色面s2y1-11-紫色面1 -1,y2] +重复减去的红色面积 1 -1,y1 -11
当你认直听取m队长给你讲述的知识后,脑洞大开,决定利用所学内容解决下述问题。在一张无限大二维网格上,存在n(n<=5000个点,点i(0<=n)坐落在(y格子上。当我们任取两个点,都可以以这两个点构成一个矩形注意:当两个点横坐标相同或纵坐标相同时退化成一条宽为1的
网格条,两个点是同一坐标时退化成一个网格,这并不影响我们的任务),我们的任务是求出这个矩形内存在多少个点?

输入

第一行输入两个整数n,m表示网格上分布着n个点,同时我们有m个矩形需要统计内部的点的数量
接下来n行,每行两个整数x,y表示点i(0<=i<n)的坐标。
接下来m行,每行两个整数k1,k2(0<=k1,k2n),表示我们查询以点k1和点k2构成的矩形内点的数量

输出

m行,每行一个整数,表示第i次询问的矩形内部的点的数量
示例 1:

输入:
4 3
0 0
0 1
1 0
1 1
0 3
0 1
2 2
输出:
4
2
1

样例解释

一共四个点,分布在(0,0),(0,1),(1,0)11)四个网格中,如图所示:
在这里插入图片描述
三次询问,0号点和3号点构成的矩形以(O,0)为左上角,(1,1)为右下角,内部包含4个点。
0号点和1号点构成的矩形以(0,0)为左上角, (0,1)为右下角,内部包含2个点。
2号点和2号点构成的矩形只有 (1,0)一个格子,内部包含1个点。

重要提示

保证60%的数据中,点的数量n<=100,查询的次数m<=100,并且所有点的坐标都在[1,100]以内,也就是说你完全可以不听取m队长的任何建议就可以得到本题目60%的分数。
保证80%的数据中,点的数量n<=5000,查询的次数m<=10000,并且所有点的坐标都在[1, 1000]以内,也就是说你只需要听会m队长的二维前缀和就可以得到本题目80%的分数。
保证100%的数据中,点的数量n<=5000,查询的次数m<=100000,并且所有点的坐标在int表示的范围内即[-2^31, 2^31-1],也就是说你既需要学会m队长讲的离散化也要学会二位前缀和才可以得到本题目100%的分数。

思路

非常经典的值域大而数据数量少的问题,可采用离散化方法;而多次查询,可采用前缀和思想预先处理,节约每次查询的时间。
离散化+二维前缀和,详见代码注释。
其中数据范围通过点的数量和查询次数来确定,每次查询是选择某个点,而点数n最多为5000,因此横坐标、纵坐标最多都为5000,确定了离散化后的数组维度N与n相同。

代码

#include <bits/stdc++.h>

using namespace std;

int n, m;
const int N = 5000 + 10;
int a[N][N], s[N][N]; // 离散化后的点数组、前缀和数组
vector<vector<int>> point; // 存点的坐标
vector<int> idx; // 存放点的原始横坐标
vector<int> idy; // 存放点的原始纵坐标
// 将横坐标离散化,映射到某个下标 用的二分查找
int findx(int x){
    int l = 0, r = idx.size() - 1;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(idx[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1; // 映射下标从1开始,便于计算前缀和
}
// 将纵坐标离散化,映射到某个下标
int findy(int x){
    int l = 0, r = idy.size() - 1;
    while(l < r)
    {
        int mid = l + r >> 1;
        if(idy[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1;
}

int main(){
    cin >> n >> m;
    // n个点
    for(int i = 0; i < n; i ++ ){
        int x, y;
        cin >> x >> y;
        point.push_back({x, y});
        idx.push_back(x);
        idy.push_back(y);
    }
    // 分别对横坐标、纵坐标排序、去重
    sort(idx.begin(), idx.end());
    idx.erase(unique(idx.begin(),idx.end()), idx.end());
    sort(idy.begin(), idy.end());
    idy.erase(unique(idy.begin(),idy.end()), idy.end());
    
    // 处理原始点,映射下标
    for(int i = 0; i < n; i ++ ){
        int x = findx(point[i][0]);
        int y = findy(point[i][1]);
        a[x][y] ++;
    }
    // 处理前缀和
    for(int i = 1; i <= idx.size(); i ++ )
       for(int j = 1; j <= idy.size(); j ++ ){
           s[i][j] = a[i][j] + s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1];
       }
    // 处理询问
    for(int i = 0; i < m; i ++ ){
        int x1, y1, x2, y2;
        int p, q;
        cin >> p >> q;
        x1 = point[p][0], y1 = point[p][1], x2 = point[q][0], y2 = point[q][1];
        x1 = findx(x1), y1 = findy(y1), x2 = findx(x2), y2 = findy(y2);
        cout << s[x2][y2] - s[x2][y1 - 1] - s[x1 - 1][y2] + s[x1 - 1][y1 - 1] << endl;
        
    }
    
    return 0;
}

时间复杂度

排序: O ( n l o g n ) O(nlogn) O(nlogn)
处理原始点,映射下标: O ( n l o g n ) O(nlogn) O(nlogn)

处理前缀和: O ( n 2 ) O(n^2) O(n2)
处理询问: O ( m ) O(m) O(m)

前缀和优化了询问,否则复杂度为 O ( m ∗ n 2 ) O(m*n^2) O(mn2)
离散化优化了数组维度N,优化后的N与点的个数n相近(可略大更保险,保证数组运算不越界),否则N需要涵盖数的范围 [ − 2 31 , 2 31 − 1 ] [-2^{31}, 2^{31}-1] [231,2311], 即 2 32 2^{32} 232,则 O ( N 2 ) O(N^2) O(N2)将严重超时,难以计算。

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

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

相关文章

学习周报-20221211

文章目录一 centos7修改系统运行级别的方法方法一方法二二 修改(忘记)centos系统的root密码三 文件的atime、mtime、ctime比较1 定义2 mtime和ctime的比较3 atime在访问文件后并不一定会修改4 相关操作命令对三个时间的影响四 Linux时区设置中的一些问题五 Linux局域网内配置yu…

微服务框架 SpringCloud微服务架构 微服务保护 34 规则持久化 34.1 规则管理模式

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 微服务保护 文章目录微服务框架微服务保护34 规则持久化34.1 规则管理模式34.1.1 规则管理模式34.1.2 规则管理模式 - 原始模式34.1.3 规则管…

android 和风图标字体移植显示墨迹天气图标

android studio版本&#xff1a;21.2.1 例程&#xff1a;newareaautov1 和风天气字体图标使用方法见&#xff1a; android 显示和风天气字体图标_kim5659的博客-CSDN博客_qweather-icons 之前做了个全自动获取天气的app,用的是墨迹的接口&#xff08;实际是科大讯飞再接入墨…

深信服面试常见算法题整理笔记

⭐️我叫恒心&#xff0c;一名喜欢书写博客的研究生在读生。 原创不易~转载麻烦注明出处&#xff0c;并告知作者&#xff0c;谢谢&#xff01;&#xff01;&#xff01; 这是一篇近期会不断更新的博客欧~~~ 有什么问题的小伙伴 欢迎留言提问欧。 文章目录1 反转链表2 排序3 设计…

Docker(二) ----Docker 的基本操作

文章目录前言一、镜像操作1.1 镜像的组成1.2 镜像的操作二、容器操作2.1 容器的基本操作2.2 容器操作的小结总结前言 前面我们学习了Docker的基本定义以及如何安装 Docker, 接下来我们对Docker的基本操作进行了解。上篇文章可点击 初始Docker 一、镜像操作 1.1 镜像的组成 镜…

SpringBoot 整合 Groovy 脚本,实现动态编程

Groovy简介 Groovy 是增强 Java 平台的唯一的脚本语言。它提供了类似于 Java 的语法&#xff0c;内置映射&#xff08;Map&#xff09;、列表&#xff08;List&#xff09;、方法、类、闭包&#xff08;closure&#xff09;以及生成器。脚本语言不会替代系统编程语言&#xff…

在idea中离线安装scala

由于网络受限&#xff0c;需要离线安装和使用scala&#xff0c;安装步骤如下。 1 安装idea scala插件 首先在idea的Help-Aboout选项中&#xff0c;查看idea的版本。 这里可以看到我的版本是2022.3&#xff0c;因此我需要下载对应版本的scala插件&#xff08;Scala插件地址&a…

git使用说明

在Windows上使用Git&#xff0c;可以从Git官网直接下载安装程序&#xff0c;然后按默认选项安装即可。 安装完成后&#xff0c;在开始菜单里找到“Git”->“Git Bash”&#xff0c;蹦出一个类似命令行窗口的东西&#xff0c;就说明Git安装成功&#xff01; 安装完成后&…

MySQL重大Bug!自增主键竟然不是连续递增

InnoDB 自增值保存在内存&#xff0c;MySQL 8.0后&#xff0c;才有了“自增值持久化”能力&#xff0c;即才实现了“若重启&#xff0c;表的自增值可以恢复为MySQL重启前的值”&#xff0c;具体情况是&#xff1a; ≤5.7&#xff0c;自增值保存在内存&#xff0c;无持久化。每…

基于免疫算法的认知无线电资源分配优化算法的matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 认知无线电&#xff08;CR&#xff09;的概念来自Joseph Mitolo博士1999年的开创性工作。它自适应地调整内部通信机制&#xff0c;通过学习&#xff0c;了解等实时变化特定的无线电操作参数&…

数据库实验四:触发器实验

实验四 触发器实验 1.实验目的 ​ 掌握数据库触发器的设计和使用方法。 2.实验内容和要求 ​ 定义BEFORE触发器和AFTER触发器&#xff0c;能够理解不同类型触发器的作用和执行原理&#xff0c;验证触发器的有效性。 3.实验重点和难点 ​ 实验重点&#xff1a;触发器的定义…

大二Web课程设计——张家界旅游网站设计与实现(HTML+CSS+JavaScript)

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

【应用】Modbus 通讯协议

Modbus 通讯协议Modbus 协议基础Modbus 存储区Modbus-RTU 协议Modbus-TCP 协议Java 实现 Modbus 通讯Modbus ReadModbus Write模拟数据进行代码测试Modbus-RTU 代码验证Modbus-TCP 代码验证SerialPortWrapper 实现类代码Modbus 协议基础 Modbus 是一种总线通讯协议&#xff0c;…

[附源码]计算机毕业设计贵港高铁站志愿者服务平台Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

Spring Bean的生命周期

一、首先我们要知道什么是Spring Bean&#xff1a;Spring Bean是Spring框架在运行管理时的对象。 二、Spring Bean的生命周期&#xff1a; 简单来说bean会经历四个阶段&#xff1a; 实例化 -》 属性赋值 -》初始化 -》销毁 下面我们来具体看一下&#xff1a; 1.实例化 Bea…

软件质量评估模型

软件质量是指软件产品满足用户要求的程度。可以从多个方面来理解此处所指的用户要求,包括用户期望的软件系统的功能、性能、可维护性、可操作性、可重用性等等。在软件项目实施过程中,经常会听到用户关于软件系统的以下一组质量评价。 软件系统没有某些方面的功能软件系统运行…

【5G MAC】NR Timing Advance(RAR TA 和 MAC-CE TA)

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

[Linux]基础命令(1)

Linux基本命令&#xff08;1&#xff09; 文章目录Linux基本命令&#xff08;1&#xff09;1.操作系统&#xff1a;&#xff08;1&#xff09;什么是操作系统&#xff1a;&#xff08;2&#xff09;为什么要有操作系统&#xff1a;2. ls命令:3. pwd指令&#xff1a;4. cd命令:5…

2022-12-11

文章目录前言PWMPwmChannelPwmAssignedHwUnitPwmChannelIdPwmCoherentUpdatePwmDutycycleDefaultPwmIdleStatePwmNotificationPwmChannelClassPwmPeriodDefaultPwmPolarityPwmReferenceChannelPwmSafetySignalPwmShiftValuePWM输出偏移的使用PwmConfigurationOfOptApiServicesP…

windows 基于 MediaPipe 实现 Holistic

主页: https://google.github.io/mediapipe/solutions/holistic.html MediaPipe Holistic pipelines 集成了姿势、面部和手部组件的独立模型&#xff0c;每个组件都针对其特定领域进行了优化&#xff0c;每个组件的推断输入图不同。 MediaPipe Holistic 首先通过 BlazePose 的姿…