离散化总结

——引入

首先就是什么时候要用离散化呢?

就是当你的数据很大比如说大到1e9甚至说更大,并且你的数据范围很小,1e5甚至更小,在这种情况下,最平均的结果也是1e9/1e5,也就是说每1万个区间长度之间,只会有一个数,这样实在太稀疏了,而且我们想要对后面的数进行调用也是完全不可能是,没有一个数组会允许你有一个1e9的下标,会直接爆数据的

这时就要用到我们今天这个简单,但是在算法竞赛中也是很实用的一个方法——离散化

离散化的定义

那么首先来说一下 ,何为离散化,离散化的本质是建立了一段数列到自然数之间的映射关系(value -> index),通过建立新索引,来缩小目标区间,使得可以进行一系列连续数组可以进行的操作比如二分,前缀和等…

摘录自海风大佬的博客:http://t.csdnimg.cn/2oT6H

单论定义的话,确实还是有些许抽象的,因此我在这里给出一个实例

1 87 345  999 999  1e9,对于这段序列,数据范围仅为6(只有6个数,但是其数据大小这跨度可真是大啊),那么我们就要去给这个序列去离散化一下  1->1 ,  87->2  ,  345->3  ,999->4,1e9->5;

这里同时说明一下,离散化是有两种离散化的,一种是保序去重离散化,另一种是保序不去重离散化

我们一般用的都是第一种离散化方法,我们来介绍一下什么是保序,保序说的是里面的大小顺序是不能变的,3小于5,那么离散化后的数据一定也是3的离散化也是要小于5的离散化的,那么什么是去重呢,那就是说,对于同一个数据,只会产生一种离散化, 比如说一开始的数据里面有两个123,那么这两个123 后面离散化对应的数据一定是相同的

那么这时候就会有同学提出疑问了,那这不就是用map可以实现的吗?map可以去实现不保序的,大部分时候那个顺序还是很重要的

因此,我们的离散化步骤为

1.排序(一般都会有固定的大小顺序去离散化,一般是从大到小排序)

2.去重

3.二分排序好的数组,去找到下标(离散化)

完成了离散化之后,后续可以进行一些前缀和,差分,二分什么的操作,同时离散化优化线段树也是一个重要的考点,这里就不展开说明了

离散化例题

P1904 天际线

题意:就是说每组输入三个数组,分别代表建筑的左边界下标,建筑的高度,建筑的右边界下标,,然后问你整个建筑群的轮廓是什么

思路:如果学过离散化和线段树的都会想到一个在2018年被国际算法组认可的算法—— 扫描线算法,然后去求矩形周长并即可

当然我自己也写了一个扫描线算法的博客,有兴趣可以看一下:http://t.csdnimg.cn/M8Ed7

但是很可惜有个大犇分享了一个提高+降成普及-的一个纯暴力的思路,然后这题就被降数据了

因此我们的思路也为,一开始假设建筑的标志符flag为0,如果碰到当前最高的位置和flag不相同的时候,就要输出这个位置的下标+这个位置的高度,然后我们在输入的时候将每个位置的的最高高度记录下来即可

#include<bits/stdc++.h>
using namespace std;
#define int long long

int H[100005];
int l,r,h;

signed main()
{
	while(cin>>l>>h>>r)
	{
		for(int i=l;i<r;i++)
		{
			H[i]=max(H[i],h);
		}
	}
	int flag=0;
	for(int i=1;i<=10000;i++)
	{
		if(H[i]!=flag)
		{
			cout<<i<<" "<<H[i]<<" ";
			flag=H[i];
		}
	}
	return 0;
}

P1955 [NOI2015] 程序自动分析

题意:就是说有t组数据,每组数据输入n个操作,然后每次输入a,b还有flag,如果flag=1,那么就说明a==b。如果flag=0,就说明a!=b

思路:我们先处理操作为1的,因为操作为我们可以用到并查集的思路,现将操作为1的放到一个集合里面,然后如果再0的时候,这两个根节点相同的两个点是0的话,那就说明为NO,反之为YES

但是这题,输入的a和b有可能很大,所以需要去进行离散化一下

#include<bits/stdc++.h>
using namespace std;
#define int long long 

int t;
int n;
struct node{
	int a;
	int b;
	int e;
}q[200005]; 
int num[400005];
int f[400005];

bool cmp(node a,node b)
{
	return a.e>b.e;
}

int cha(int x)
{
	if(f[x]==x)
	return x;
	return f[x]=cha(f[x]);
}

void bing(int a,int b)
{
	f[cha(a)]=cha(b);
	return ;
}

signed main()
{
	cin>>t;
	while(t--)
	{
		memset(q,0,sizeof(q));
		memset(num,0,sizeof(num));
		memset(f,0,sizeof(f));
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>q[i].a>>q[i].b>>q[i].e;
			num[i]=q[i].a;
			num[i+n]=q[i].b;
		}
		sort(num+1,num+1+2*n);
		sort(q+1,q+1+n,cmp);
		int len=unique(num+1,num+1+2*n)-(num+1);
		for(int i=1;i<=n;i++)
		{
			q[i].a=lower_bound(num+1,num+1+len,q[i].a)-num;
			q[i].b=lower_bound(num+1,num+1+len,q[i].b)-num;
		}
		int flag=1;
		for(int i=1;i<=len;i++)
		{
			f[i]=i;
		}
		for(int i=1;i<=n;i++)
		{
			if(q[i].e==1)
			{
				bing(q[i].a,q[i].b);
			}
			else
			{
				if(cha(q[i].a)==cha(q[i].b))
				{
					flag=0;
					break;
				}
			}
		}
		if(flag==1)
		{
			cout<<"YES\n";
		}
		else
		{
			cout<<"NO\n";
		}
	}
	return 0;
}

P3029 [USACO11NOV] Cow Lineup S

题意:就是有给你n个牛的位置以及种类,然后让你判断最少多长的距离可以覆盖所有种类的牛

思路:我们发现,数据范围很大,因此,我们要对齐进行离散化,然后就会发现其实他和滑动窗口很像,因此用单调队列,双指针都可以解决,我用的双指针


#include<bits/stdc++.h>
using namespace std;
#define int long long

int n;
struct node{
	int x,id;
}a[50005];
map<int,int> mp;
map<int ,bool> vis;
int minn=0x3f3f3f3f;
bool cmp(node x,node y)
{
	return x.x<y.x;
}
signed main()
{
	cin>>n;
	int cnt=0;//用于统计所有种类的个数 
	for(int i=1;i<=n;i++)
	{
		cin>>a[i].x>>a[i].id;
		if(vis.find(a[i].id)==vis.end())//如果这种牛没出现过 
		{
			vis[a[i].id]=1;
			cnt++;
		}
	}
	sort(a+1,a+1+n,cmp);
	int l=1,r=1,num=1;
	int flag=0;
	if(num==cnt)
	{
		minn=a[1].x-1;
		flag=1;
	}
	mp[a[1].id]++;
	while(r<=n)
	{
		if(flag==0)
		{
			if(r==n)
			{
				break;
			}
			r++;
			if(mp.find(a[r].id)==mp.end()||mp[a[r].id]==0)
			{
				num++;
			}
			mp[a[r].id]++;
			if(num==cnt)
			{
				minn=min(minn,a[r].x-a[l].x);
				flag=1;
			}
		}
		else
		{
			l++;
			if(mp[a[l-1].id]==1)
			{
				num--;
				flag=0;
			}
			if(flag==1)
			{
				minn=min(minn,a[r].x-a[l].x);
			}
			mp[a[l-1].id]--;
		}
	}
	cout<<minn;
	return 0;
}

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Matlab中,有多种方法可以用来进行离散化处理。其中一种方法是使用c2d函数,该函数可以将连续系统转换为离散系统。在该函数中,可以通过设定参数来选择不同的离散化方法。例如,可以使用'method'参数来指定具体的离散化方法,如:'zoh'表示零阶保持,'foh'表示一阶保持,'tustin'表示双线性变换等。通过这些方法,可以将连续系统的传递函数转换为离散化的分子和分母形式,使用tfdata函数可以提取出这些分子和分母。 另外,对于绘制图形的离散化方法,可以使用surf函数或mesh函数来进行绘图。这两个函数可以根据给定的坐标数组和函数值数组来绘制三维图形。如果坐标数组是一维的,可以使用meshgrid函数生成矩形格点坐标数组。同时,可以使用contourf函数在已有的图形基础上绘制等高线。还可以使用colormap函数来设置图形的色图,可以选择不同的预定义色图来进行配色。此外,还可以使用shading选项来调整图形的浓淡处理效果,可以选择Flat、Interp或Faceted等选项来改变图形的着色方式。 总结起来,Matlab中提供了多种离散化方法,包括将连续系统离散化的方法和绘制图形的离散化方法。具体选择哪种方法取决于具体的需求和应用场景。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [通过MatLab将传递函数离散化](https://blog.csdn.net/baidu_37173242/article/details/78839286)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [matlab z变换离散化_Matlab数据可视探索](https://blog.csdn.net/weixin_39950081/article/details/109917108)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值