离散化的思想
離散化是什么:一些數字,他們的范圍很大(0-1e9),但是個數不算多(1-1e5),并且這些數本身的數字大小不重要,重要的是這些數字之間的相對大小(比如說某個數字是這些數字中的第幾小,而與這個數字本身大小沒有關系,要的是相對大小)(6 8 9 4 離散化后即為?2 3 4 1)(要理解相對大小的意思)(6在這4個數字中排第二小,那么就把6離散化成2,與數字6本身沒有關系, 8,9,4亦是如此)
離散化思想:因為數字太大,導致沒有辦法開那么大的數組,又因為數字個數并不多,這時候就可以對它們進行離散化,離散化是改變了數字的相對大小,例如,有500000個數字,他們的范圍是0-1e9的,這樣就滿足離散化的條件。
就比如說,你可以開一個5e5的數組,但是你不能開一個1e9的數組。只改變這些數字的相對大小
第一種離散化
(包含重復元素,并且相同元素離散化后也要相同,推薦使用)
 離散化以前一直搞不懂是怎么實現的,看了一個代碼才明白。
原來的a[i]離散化后成了后來的a[i];
離散化后的a[i]范圍是(1-m);
 舉個栗子:
 原序列:6 9 4 6 4
 排序后:4 4 6 6 9
 unique(元素去掉重復的)后:4 6 9 6 9
為什么unique去重后是4,6,9,6,9,而不是4,6,9,4,9,大家運行下面的代碼即可
(大佬的解答:unique去重完后面的元素是不變的,所以是4 6 9 6 9)
#include <cstdio> #include <algorithm> using namespace std; int a[10]={6,9,4,6,4}; int main() {int n=5;sort(a,a+n);//排序后4 4 6 6 9n=unique(a,a+n)-a;for(int i=0;i<5;i++)printf("%d ",a[i]);printf("\n");//最后輸出4 6 9 6 9//SiriusNEO大佬的解答:unique去重完后面的元素是不變的,所以是4 6 9 6 9,具體可以看C++ Reference的源碼 }unique有一個返回值,例如有十個有序的數列3 3 5 5 6 6 6 7 7 8,不重復的數字有五個,使用unique去重之后數列變成了3 5 6 7 8 6 6 7 7 8,它只改變了前五個數字后邊的不變,返回值是 最后一個改變的數字的地址。so:m=unique(t+1,t+1+n)-t-1;一般要減去首地址(t+1),m為不重復的數字的個數
?第二種離散化
(復雜度低,1.包含重復元素,并且相同元素離散化后不相同,2.不包含重復元素,并且不同元素離散化后不同,符合這兩種的其中一個,推薦使用
struct A {int x, idx;bool operator < (const A &rhs) const{return x < rhs.x;}//也可以寫個cmp函數排序 }; A a[MAXN]; int rank[MAXN]; int n; scanf("%d",&n); for(int i = 1; i <= n; ++i) {scanf("%d", &a[i].x);a[i].idx = i; } sort(a + 1, a + n + 1);for(int i = 1; i <= n; ++i) {rank[a[i].idx] = i; }給你們個例子:
 i ? ? ?1 2 3 4
 x ? ? 6 8 9 4
 idx ?1 2 3 4
 排序后:
i ? ???1 2 3 4 ?//離散化后的數字
 x ? ? 4 6 8 9?
 idx ?4 1 2 3 ?//數字原來的所在的位置編號
將上面兩行黑體數字對應起來 即是:rank[4]=1,rank[1]=2,rank[2]=3,rank[3]=4; ?//rank[i]=j表示將原來在第i個位置上的數字離散化成j
 so:
 rank[1]=2;
 rank[2]=3;
 rank[3]=4;
 rank[4]=1;
 so: ? 6 8 9 4
就離散化為2,3,4,1
如果你想用原來的數字,就用排過序的結構體a[2]=6,a[3]=8,a[4]=9,a[1]=4; //a[i]=j表示排過序后現在的a數組里第i個數字的是j。j也就是第i小。
 a[i]是原來的數字;
 rank是離散化后的數字;
?
總結
 
                            
                        - 上一篇: 最优化学习笔记(六)——牛顿法性质分析
- 下一篇: 因子和,因子数,1到n的因子和,1到n的
