离散化算法(c++)(自用)

一.概念  

离散化数据是将一组不连续的数据转换为一组连续的整数,常用于处理具有大量重复值或需要连续编号的情况

例如,{400,5000,1,3000,200}通过离散化我们将其变为{3,5,1,4,2}.也就是说离散化,把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。通俗的说,离散化是在不改变数据相对大小的条件下,对数据进行相应的缩小。(from百度)

基本步骤

1.排序

2.去重

3.离散化索引

二.例题

假定有一个无限长的数轴,数轴上每个坐标上的数都是0。现在,我们首先进行 n 次操作,每次操作将某一位置x上的数加c。接下来,进行 m 次询问,每个询问包含两个整数l和r,你需要求出在区间[l, r]之间的所有数的和。

输入格式
 第一行包含两个整数n和m。

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

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

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

数据范围
 −109≤x≤109,
 1≤n,m≤105,
 −109≤l≤r≤109,
 −10000≤c≤10000
 输入样例:
 3 3
 1 2
 3 6
 7 5
 1 3
 4 6
 7 8
 输出样例:
 8
 0
 5 

三.例题讲解

我们将l和r的大小范围看成数轴的范围,n和m看成点的坐标。

由于r和l的范围较大,而n和m的范围较小即为调用的数字较少,所以我们可以将其离散化,缩短数周的空间,将其离散化。

因此根据题目,我们可以得出此图

四.代码实现

#include<iostream>
#include<vector>
#include<algorithm>

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

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

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

输入格式
 第一行包含两个整数n和m。

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

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

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

数据范围
 −109≤x≤109,
 1≤n,m≤105,
 −109≤l≤r≤109,
 −10000≤c≤10000
 输入样例:
 3 3
 1 2
 3 6
 7 5
 1 3
 4 6
 7 8
 输出样例:
 8
 0
 5 
*/



using namespace std;
typedef pair<int, int> PII;	//使用PII来代替pair<int,int>,从而使代码更加简洁易懂

const int N = 30010; 

int n, m;//输入值
int a[N], s[N];//定义数组a[]和s[]

//alls为总的坐标
vector<int> alls;	

vector<PII> add, query;	

//函数功能:查找alls中x的下标
//函数返回值:alls中x所对应的下标+1

//二分搜索法
//用lowerbound也可以lower_bound(alls.begin(),alls.end(),x) - alls.begin() ;

int find(int x)
{
	int l = 0, r = alls.size();
	while (l < r)
	{
		int mid = (l + r) / 2;
		if (alls[mid] >= x)
		{
			r = mid;
		}
		else { l = mid + 1; }
	}
	return r + 1;	//为了计算前缀和方便所以+1
}

int main()
{

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

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

	cin >> n >> m;

	for (int i = 0; i < n; i++)
	{
		int x, c;
		cin >> x >> c;
		add.push_back({ x, c });
		alls.push_back(x);//坐标放入adds数组中
	}

	for (int i = 0; i < m; i++)
	{
		int l, r;
		cin >> l >> r;

		query.push_back({ l, r });

		//将所有的坐标放进alls中
		alls.push_back(l);
		alls.push_back(r);
	}

	//排序
	sort(alls.begin(), alls.end());

	//去重
	//unique返回一个新的结束迭代器,作为下一步的开始,alls.end()返回当前结束位置,删除这区间所有元素
	alls.erase(unique(alls.begin(), alls.end()), alls.end());

	//构造离散化数组a[i]
	for (auto item : add)
	{
		int i = find(item.first);//构建[a]找到每个坐标x的位置

		a[i] += item.second;//对a[]中每个元素加上c
	}

	//构造前缀和数组s[i]
	//因为前面+1了所以这里i= 1

	for (int i = 1;i <= alls.size(); i++) 
	{
		s[i] = s[i - 1] + a[i];//获得前缀和
	}

	for (auto item : query)
	{
		int l = find(item.first), r = find(item.second);
		
		//区间和就是s[r]-s[l-1],相当于一个线段
		cout << s[r] - s[l - 1] << endl;
	}

	system("pause");
	return 0;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
状态空间离散算法是指将连续状态空间转换为离散状态空间的过程。在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中进行进一步的处理和分析。离散的状态空间可以方便地应用于控制系统设计、优和仿真等领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值