1. 程式人生 > >離散化:兩種離散化方式詳解

離散化:兩種離散化方式詳解

引入

離散化,就是把一些很離散的點給重新分配。

舉個例子,如果一個座標軸很長(>1e10),給你1e4個座標,詢問某一個點,座標比它小的點有多少。

很容易就知道,對於1e4個點,我們不必把他們在座標軸上的位置都表示出來,因為我們比較有多少比它小的話,只需要知道他們之間的相對大小就可以,而不是絕對大小,這,就需要離散化。

而離散化又分為兩種,分為的兩種是對於重複元素來劃分的。第一種是重複元素離散化後的數字相同,第二種就是不同。

第一種

其實就是用一個輔助的陣列把你要離散的所有資料存下來。

然後排序,排序是為了後面的二分。

去重,因為我們要保證相同的元素離散化後數字相同。

再用二分把離散化後的數字放回原陣列。

程式碼如下。

#include<algorithm> // 標頭檔案 
//n 原陣列大小 num 原陣列中的元素 lsh 離散化的陣列 cnt 離散化後的陣列大小 
int lsh[MAXN] , cnt , num[MAXN] , n;
for(int i=1; i<=n; i++) {
	scanf("%d",&num[i]);
	lsh[i] = num[i];	
}
sort(lsh+1 , lsh+n+1);
cnt = unique(lsh+1 , lsh+n+1) - lsh - 1;
for(int i=1; i<=n; i++)
	num[i] = lower_bound(lsh+1 , lsh+cnt+1 , num[i]) - lsh;

注意事項:

1.去重並不是把陣列中的元素刪去,而是重複的部分元素在陣列末尾,去重之後陣列的大小要減一

2.二分的時候,注意二分的區間範圍,一定是離散化後的區間

3.如果需要多個數組同時離散化,那就把這些陣列中的數都用陣列存下來

第二種

第二種方式其實就是排序之後,列舉著放回原陣列

用一個結構體存下原數和位置,按照原數排序

我結構體裡面寫了個過載,也可以寫一個比較函式

最後離散化後數在rank[]rank[]裡面

#include<algorithm>
struct Node {
	int data , id;
	bool operator < (const Node &a) const {
		return data < a.data;
	}
};
Node num[MAXN];
int rank[MAXN] , n;
for(int i=1; i<=n; i++) {
	scanf("%d",&num[i].data);
	num[i].id = i;
}
sort(num+1 , num+n+1);
for(int i=1; i<=n; i++)
	rank[num[i].id] = i;

總結

用的最多的是第一種方法,第二種方法感覺比較陌生,不過還是需要學的。

有不對的地方歡迎更正,只要看見一定採納。