离散化算法

        离散化算法的本质就是,将分布范围很大,但是密度很小的数据,变成分布范围很小,密度 很密的过程。例如,一个数组的元素是1,50,5000,60000,这个数组的范围跨度很大,但是密度很小 ,所以为了能够进行方便的查询和区间运算,我们将他们映射到连续的范围很小的数组中去。

             例如:将1映射为新数组1的下标的位置,50映射到 新数组下标2的位置,以此类推。

              而需要进行区间数据操作的时候,就需要将给出的区间下标转换为离散化后的下标进行数据操作就可以了。

        

 离散化题目的思路想法

       

假定有一个无限长的数轴,数轴上每个坐标上的数都是 00。

现在,我们首先进行 n次操作,每次操作将某一位置 x 上的数加 c。

接下来,进行 m次询问,每个询问包含两个整数 l和 r,你需要求出在区间 [l,r] 之间的所有数的和。

输入格式

第一行包含两个整数 n 和 m。

接下来 n行,每行包含两个整数 x和 c。

再接下来 m行,每行包含两个整数 l和 r。

输出格式

共 m 行,每行输出一个询问中所求的区间内数字和。

        思路:在题目中提到的数据的范围跨度很大,同时如果需要求得区间和的话,可以使用前缀和的方式。为了使用前缀和的方式需要降低区间的范围,以降低时间运行的复杂度。

        具体实现方式:扫描需要用到的所有数据,开辟一个 n*数据长度+2*m个查询的数组,后面再进行去重排序和离散化,最后在进行前缀和输出就可以了!

        注意:在这个算法中会创造两个数组,一个数组用来存储操作数据(包含数学运算和区间查询的所有下标 )alls[ ],一个直接用来记录操作之后的结果数组 res[ ]。

  ok,后面解决一些可能有疑惑的地方:

1.  为什么需要开辟n+2m个长度的数组?

        因为在解题的时候会创建一个数组专门用来存储需要操作的下标,下标与数就是对应关系,即存储的时候数据的大小和下标是相等的。所以,只需要将下标得到,并且存储在这个数组中,就可以对其进行操作了。

2. 为什么需要去重和排序?

        去重的原因: 在前面的插入和数据操作的下标,跟后面进行数据区间和的查询的下标是有可能重合的,为了防止在通过遍历这个存储下标数组的时候,将结果数组加上了两次,出现数据不对的情况。

        排序的作用:主要是为了在后续进行区间和的查询的时候能够得到正确的数值,因为如果不排序的话就会使得各个区间和并不对,是混乱的

        例如: 在1的位置加2,3的位置加3,2的位置加上2,查询[1 , 3]的区间和,数组原始长度是5。

        那么,通过处理后的 alls 数组的情况就是:[1,2,3,5] , 数组res 的结果就是:[2,2,3,0](假设下标重1开始)

        如果只是去重的话,有可能出现不按照顺序出现的情况,当然上面的情况是一种很理想的情况,如果出现乱序的情况,比如:alls是[1,3,5,2]的话,res就变成了[2, 3 ,2, 0]就会导致后续在求前缀和的时候出现区间和不对的情况。

        举一个例子:正确的区间和应该是:[1,3] -> [7],

                             没有排序出现顺序错误的情况下的结果是: [1,3] -> [5]

        出现这种情况的原因,是因为后续直接进行前缀和的时候,直接将res 中的前面的数据加上的,并不会再次判断下标的问题。

3.  开辟的两个数组的作用的是什么?

          第一个数组alls的作用:  用来记录需要进行操作的数据的下标和需要进行数学运算的数据,以及需要进行查询的区间数据。

        第二个数组:是用来记录离散化之后,并且被操作之后的数据数组。

4. 如何求区间和和返回正确的数据?

        这个就需要用到 res 数组了,直接对res数组求前缀和 s 数组,并且保存起来就可以了。

        如何返回正确的数据: 将需要查询的区间值进行相同的离散化,找到离散化之后的下标,然后再在 s 数组中,使用s[ r ] - s[ l - 1 ]就可以了。

        到这一步就可以更加深刻的理解为什么事先需要存入查询的区间值了,这一步是相当的女少口阿,因为在这一步的时候直接将[ 0, l ] 和[ 0 , r ] (l 和 r 就是需要查询的区间的左右端点的前缀和求出来了,然后直接使用s[ r ] - s[ l - 1 ]就可以求出需要求出的区间的数值了。

离散化数据的模板

//这一步是进行数据的去重和排序
//直接背一下这个方法就可以了
sort(alls.begin(), alls.end());
alls.erase(unique(alls.begin(), alls.end()), alls.end());



//这一步就是找到离散化之后的下标的位置
//这里展示的是二分查找的方法,当然可以使用hashMap直接得到原坐标和离散化之后的映射,这样就可以使得时间复杂度从log2(n) 变成O(1)

//这里使用的数组就是上面调用方法之后的数组alls
int find(int x){
     int l = 0,r = all.size() - 1;
    //这一步是为了找到第一个大于给定数据的位置
     while(l < r){
        int mid = l + r >> 1;
        if(all[mid] >= x) r = mid;
        else l = mid + 1;
    }
    //这一步加1,是为了后续在进行前缀和的时候可以直接从1开始
    return r + 1;
}

 

            

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
状态空间离散算法是指将连续状态空间转换为离散状态空间的过程。在Matlab中,我们可以使用以下步骤进行离散。 1. 确定状态空间的维度和范围:首先,我们需要确定状态空间的维度,例如,如果状态空间由两个变量组成,我们可以定义它们为 x 和 y。接下来,我们需要确定每个变量的范围,例如,x 的取值范围为 [-5, 5],y 的取值范围为 [-10, 10]。 2. 设置离散步长:接下来,我们需要设置离散的步长。步长可以根据问题的复杂度和需要进行调整。通常,步长越小,离散的精度越高,但计算量也会增加。在本例中,我们可以设置 x 和 y 的步长为 0.5。 3. 构建状态空间矩阵:使用上述步长,我们可以根据状态空间的维度和范围构建一个状态空间矩阵。在本例中,我们可以创建一个矩阵 X,其每一行由一个状态向量 [x, y] 组成。X 的大小将取决于每个变量的范围和步长,例如,在上述范围和步长下,X 的大小将为 21x41,因为每个变量都有 21 个步长和 41 个步长。 4. 应用离散状态空间:通过使用状态空间矩阵 X,我们可以将连续状态转换为离散状态。对于每个连续状态,我们可以通过计算其在矩阵 X 中的最近邻来找到对应的离散状态。最近邻可以使用欧氏距离或其他距离度量进行计算。 使用这个算法,我们可以将连续状态空间离散为有限的离散状态,并且可以在Matlab中进行进一步的处理和分析。离散的状态空间可以方便地应用于控制系统设计、优和仿真等领域。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GK742

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值