離散化,就是把一些很離散的點給重新分配。
舉個例子,如果乙個座標軸很長(>1e10),給你1e4個座標,詢問某乙個點,座標比它小的點有多少。
很容易就知道,對於1e4個點,我們不必把他們在座標軸上的位置都表示出來,因為我們比較有多少比它小的話,只需要知道他們之間的相對大小就可以,而不是絕對大小,這,就需要離散化。
而離散化又分為兩種,分為的兩種是對於重複元素來劃分的。第一種是重複元素離散化後的數字相同,第二種就是不同。
其實就是用乙個輔助的陣列把你要離散的所有資料存下來。
然後排序,排序是為了後面的二分。
去重,因為我們要保證相同的元素離散化後數字相同。
再用二分把離散化後的數字放回原陣列。
**如下。
#include// 標頭檔案
//n 原陣列大小 num 原陣列中的元素 lsh 離散化的陣列 cnt 離散化後的陣列大小
int lsh[maxn] , cnt , num[maxn] , n;
for(int i=1; i<=n; 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.如果需要多個陣列同時離散化,那就把這些陣列中的數都用陣列存下來
第二種方式其實就是排序之後,列舉著放回原陣列
用乙個結構體存下原數和位置,按照原數排序
我結構體裡面寫了個過載,也可以寫乙個比較函式
最後離散化後數在rankrank裡面
#includestruct node
};node num[maxn];
int rank[maxn] , n;
for(int i=1; i<=n; i++)
sort(num+1 , num+n+1);
for(int i=1; i<=n; i++)
rank[num[i].id] = i;
先送一道有離散化的題:luogu1955
很水的一道題,解析在這:noi2015程式自動分析
用的最多的是第一種方法,第二種方法感覺比較陌生,不過還是需要學的。(20190506第二種方法on啊,,第一種是nlogn的,但是第二種方法只適用於無重複元素的。對於第一種方法,當所有a[i]<2e6這樣子時,可以開陣列預處理一下每個數的位置,也可以優化到nlogn預處理之後單次查詢o1,有的同學說,那你a[i]<2e6了,直接開陣列不就行了嗎還要啥離散化,但是你別忘了,你萬一是個二維陣列呢?怎麼開?比如這個題【codeforces - 255c】)。
**
演算法筆記 初識離散化
對於一些數值很大但數量不大的數,我們更關心它們的相對大小,更想要知道這個數是第幾大或者第幾小,這個時候就需要把這些數離散化。感謝大佬 include include include define maxn 1005 using namespace std int main sort t 1,t 1 ...
離散化1(演算法)
對於值域比較大 0 10 9 對於這些值,我們需要把他們當成下標來做,我們可以把它對映到從1開始連續的陣列之中儲存 假設 a a有序 對映之後 1 0 3 1 100 2 2000 3 5000000 4 問題 a中可能存在重複元素 所以需要去重 vector int a 儲存所有待離散化的值 so...
基礎演算法 離散化
離散化主要是通過建立乙個對映,將分散的元素的位置對映成連續的位置以節約空間。說明 x為題目要進行操作的陣列元素的下標,y為經過離散化後的下標。原理 若不離散化,則針對該例需要開乙個大小為9000000的陣列儲存操作結果!通過建立乙個對映陣列來儲存所有要進行操作的下標x,然後將其排序去重,每次操作x位...