离散化学习笔记

news/2025/2/22 22:23:37/文章来源:https://www.cnblogs.com/FrankWKD/p/18717993

离散化学习笔记

OP:又是一如既往的周更。。。水死了

定义

  • 离散化将数字映射为是第几小的数,其保证数据在Hash之后仍然保持原来的全/偏序关系,能够解决:通过元素相对大小即可解决的问题。
  • 其实本质上就是哈希的一种特殊规则而已。(离散化简化了不止亿点)

目标

  • 将一堆乱序且不保证全部相邻的数组变成紧凑且在这些数之间的每个数都被充分利用。
  • 说人话:将每个数改为自己是第几小的数。(我语文太差,具体请看例子:)

步骤

  • 1.数组中存在重复的元素,因此需要排序&去重;
  • 2.计算每个 \(a_i\) 是第几小的数。【二分查找】

代码:

点击查看代码 图源`v.czos.cn`,侵删。

习题

又到了令人欢快的做题时间
本课习题:共9道题,2道难题。来源:oj.czos.cn

01 统计数字

点击查看题面内容

解法:其实就是简单的离散化,因为 \(n\) 比较大,所以我们考虑使用桶排序来统计这些数的出现次数。即: \(ans_i\) 表示 数值为 \(i\) 的数的出现次数。因为数组最大开 \(10^7\) (保守估计),且 \(n\) 明显小于 \(A_i\) 的数据范围,所以肯定在这中会有出现次数为 \(0\) 的数。所以我们先把数组离散化,然后桶排序直接输出即可。

点击查看代码
//提示:此代码遵守GNU GPL 2.0开源协议。
//作者:FrankWkd  
//博客:https://cnblogs.com/FrankWkd
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
const int M = 1e4 + 10;
int a[N], b[N], c[M];
int n, k;
int main() {cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];b[i] = a[i];}sort(b + 1, b + 1 + n);k = unique(b + 1, b + 1 + n) - b - 1;for (int i = 1; i <= k; i++) {a[i] = lower_bound(b + 1, b + 1 + k, a[i]) - b;c[a[i]]++;}for (int i = 1; i <= k; i++) {cout << b[i] << " " << c[i] << endl;}return 0;
}

02 供水点

点击查看题面内容

解法:定义 \(ans\) 数组,存储每个位置可以不推车来的人数,遇到一个 \([L,R]\)就将 \(ans\) 对应的区间加一,这个过程可以用差分来完成。最后 \(ans\) 数组里面最大的值就是结果。\([L,R]\) 太大需要离散化。

点击查看代码
//提示:此代码遵守GNU GPL 2.0开源协议。
//作者:FrankWkd  
//博客:https://cnblogs.com/FrankWkd
#include <bits/stdc++.h>
using namespace std;int a[200010];
int b[200010];
int ans[400010];
int all[400010];int main() {int n;cin >> n;int k = 0;for (int i = 1; i <= n; i++) {cin >> a[i] >> b[i];all[++k] = a[i];all[++k] = b[i];}sort(all + 1, all + 1 + k);k = unique(all + 1, all + k + 1) - all - 1;for (int i = 1; i <= n; i++) {a[i] = lower_bound(all + 1, all + 1 + k, a[i]) - all;b[i] = lower_bound(all + 1, all + 1 + k, b[i]) - all;ans[a[i]]++, ans[b[i] + 1]--;}int maxx = 0;for (int i = 1; i <= k; i++) {ans[i] += ans[i - 1];maxx = max(maxx, ans[i]);}cout << maxx << endl;
}

03 自动灌溉

点击查看题面内容

解法:跟T2差不多,都要离散化 \([L,R]\) ,只是询问略有不同,求区间和用什么?前缀和啊

点击查看代码
//提示:此代码遵守GNU GPL 2.0开源协议。
//作者:FrankWkd  
//博客:https://cnblogs.com/FrankWkd
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
int ans[1010100];
int n, m, k;
int p[100010], x[100010];
int l[100010], r[100010];
int all[600010];
int main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) {cin >> p[i] >> x[i];all[++k] = p[i];}for (int i = 1; i <= m; i++) {cin >> l[i] >> r[i];all[++k] = l[i];all[++k] = r[i];}sort(all + 1, all + 1 + k);k = unique(all + 1, all + 1 + k) - all - 1;for (int i = 1; i <= n; i++) {p[i] = lower_bound(all + 1, all + 1 + k, p[i]) - all;ans[p[i]] += x[i];}for (int i = 1; i <= m; i++) {l[i] = lower_bound(all + 1, all + k + 1, l[i]) - all;r[i] = lower_bound(all + 1, all + k + 1, r[i]) - all;}for (int i = 1; i <= k; i++) {ans[i] += ans[i - 1];}for (int i = 1; i <= m; i++) {cout << ans[r[i]] - ans[l[i] - 1] << endl;}
}

04 饲养母鸡

点击查看题面内容

解法:跟T2差不多,问的问题是一样的,但是新加入了两条规则。那我们对于每个 \([L,R]\) ,将 \(ans\) 数组中的区间 \([0,L-1]\) 加上 \(X\) (前缀和),再将 \([L,R]\) 加上 \(Y\) ,最后将 \([R+1,最后]\) 加上 \(Z\)。直接前缀和完成。那最后是哪里呢?因为从 \(R+1\) 一直到最后都要加上 \(Z\),那直接将 \(ans_{r+1}\) 加上 \(Z\),然后就能够一直加到最后了。输出 \(ans\) 数组的最大值即可。

点击查看代码
//提示:此代码遵守GNU GPL 2.0开源协议。
//作者:FrankWkd  
//博客:https://cnblogs.com/FrankWkd
#include <bits/stdc++.h>
using namespace std;int l[20010], r[20010];
int n, x, y, z;
int all[100100];
int k;
int ans[100100];
int main() {cin >> n >> x >> y >> z;for (int i = 1; i <= n; i++) {cin >> l[i] >> r[i];all[++k] = l[i], all[++k] = r[i];}sort(all + 1, all + 1 + k);k = unique(all + 1, all + 1 + k) - all - 1;for (int i = 1; i <= n; i++) {l[i] = lower_bound(all + 1, all + 1 + k, l[i]) - all;r[i] = lower_bound(all + 1, all + 1 + k, r[i]) - all;ans[1] += x, ans[l[i]] -= x;ans[l[i]] += y, ans[r[i] + 1] -= y;ans[r[i] + 1] += z;}int maxx = 0;for (int i = 1; i <= k; i++) {ans[i] += ans[i - 1];maxx = max(maxx, ans[i]);}cout << maxx << endl;
}

05

点击查看题面内容

解法:

点击查看代码
//提示:此代码遵守GNU GPL 2.0开源协议。
//作者:FrankWkd  
//博客:https://cnblogs.com/FrankWkd

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java知识面试day2

1.说出java和c++的区别java是一个纯粹的面向对象语言,所有的对象都继承于java. lang.Object,C++兼容C,不但支持面向对象也支持面向过程 java有着一次编译四处运行的跨平台特性。 java不具有指针,但具有垃圾回收。 java不支持多重继承,只能通过实现多个接口去达到相同目的2.…

继承中构造方法访问特点--java 进阶day01

1.子类不可以继承父类的构造方法构造方法的名称必须与类名一致,上图中类名是Zi,而构造方法名是Fu,肯定不行 2.子类在初始化之前,需要对父类初始化 子类在初始化的过程中,很有可能会调用到父类的数据,如果父类没有提前初始化,子类就无法调用这些数据3.通过在子类中访问父…

Mysql莫名其妙爆出拒绝访问问题的原因及解决方案

本文记录使用Mysql作为数据库时发生拒绝访问问题的解决方案Mysql出现拒绝连接问题 ⛄问题原因 : Mysql密码错误,本机上并不是只有一个Mysql服务,我们在开机时启动了并非以前使用的那个Mysql服务,所以造成了密码的错误🌟解决方案 :手动关闭当前正在启用的Mysql服务,尝试找…

Codes 开源 免费 研发项目管理平台 3.0.0 版本发布及创新的轻IPD实现

Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台,支持云端认证、本地部署、全部功能开放,并且对 30 人以下团队免费。它通过创新的方式简化研发协同工作,使敏捷开发更易于实施。采用轻量化的 IPD 模式实现,且融合了敏捷 。轻 IPD 主要解决多项目交付的研发过程管理,…

2025/2/15课堂记录

数字转换,皇宫看守,树上dp,树的直径目录数字转换 皇宫看守数字转换这是一道树的直径题。 首先,树的直径定义是:树上两个结点之间的最短(加权)路中最长的一条路径(和二分答案没关) 但由于贪心思想,这个路径一定起点终点是两片叶子结点如图,这棵树的直径就是5,即节点…

基于CPS-SPWM链式STATCOM系统在电压不平衡环境下控制策略的simulink建模与仿真

1.课题概述基于CPS-SPWM链式STATCOM系统在电压不平衡环境下控制策略的simulink建模与仿真。利用电压外环PI调节器得到有功 电流指令值结合由负载侧电流检测 到 的无功 电流指令值 ,经由 状态解耦PI调节的电流内环控制器输出直接得到的是输出电压的指令值,用此信号作为采用控制…

【库】Coravel Schedule任务调度

Coravel 通过使高级应用程序功能(如任务/作业调度、排队、缓存、邮件(以及更多!))易于访问且易于使用,帮助开发人员快速启动并运行 .NET 应用程序。具有简单、富有表现力和直接的语法。   下面是简单的用法,通过注入Scheduler和在中间件中定义调度的实现,来完成简单的…

【库】用Rin透视Web请求

Rin 可以捕获对 ASP.NET Core 应用程序的 HTTP 请求,并为捕获的数据提供查看器。它是调试 Web 应用程序(例如,网站、API 应用)的有用工具。先看如下代码:var builder = WebApplication.CreateBuilder(args); builder.Logging.AddRinLogger(); builder.Services.AddRin(); …

【蓝桥训练记录】第 26 场 蓝桥月赛

训练情况赛后反思 这场怎么都是猜猜乐+典题,做不出来的题真的不会了 A题 显然 2025 里面有多少个 15,除法向上取整即可点击查看代码 #include <bits/stdc++.h> // #define int long long #define endl \nusing namespace std;void solve(){cout<<ceil(1.0*2025/15…

光纤三维布里渊温度和应变分布matlab模拟与仿真

1.程序功能描述 光纤三维布里渊温度和应变分布matlab模拟与仿真。其中 , 布里渊散射是光波与声波在光纤中传播时相互作用而产生的光散射过程 , 在不 同的条件下 , 布里渊散射又分别以自发散射和受激散射两种形式表现出来 。 2.测试软件版本以及运行结果展示MATLAB2022A版…