離散化


  本來應該是很簡單的東西,但是之前學長講的時候也沒怎么聽,然后現在遇到需要離散化的題目就有點茫然了。看了下網上大佬們的博客,基本理解了,做個記錄。

  以下內容部分思路來自:

  https://blog.csdn.net/xiangaccepted/article/details/73276826


  

  離散化,把無限空間中有限的個體映射到有限的空間中去,以此提高算法的時空效率。這是百度百科上的定義。那么舉個栗子,某個題目告訴你有1e5個數,每個數大小不超過1e9,要你對這些數進行操作(比如並查集之類的)。那么肯定不能直接開1e9大小的數組,但是1e5的范圍就完全沒問題。在舉個栗子,現在對{4,7,6,9}進行離散化,那么得到的結果是{1,3,2,4},也就是說,當我們並不需要這些數據具體是多少時,就只需要知道他們的相對大小就行了。

 


 

  離散化有兩種方法:

  第一種, 先看一段代碼:  

const int N=1e5+7;
int t[N],a[N];
int main()
{
  cin>>n;
  for(int i=1;i<=n;i++)
    cin>>a[i],t[i]=a[i];
  sort(t+1,t+n+1);
  m=unique(t+1,t+n+1)-t-1;
  for(int i=1;i<=n;i++)
    a[i]=lower_bound(t+1,t+m+1,a[i])-t;
}

 

  在這段代碼中,a[]經過離散,范圍就變成了m。解釋一下,unique是c++自帶的一個函數,表示對一個數列去重,然后返回不重復的元素個數,當然在后面要減去首地址。那么這種離散化對於有重復元素的數列也可以適用,但復雜度相對后面要講的第二種方法會高些。

  舉個栗子

  {6,8,4,9,5,6,7,4},首先排序后得到{4,4,5,6,6,7,8,9},去重{4,5,6,7,8,9},然后原序列就變成了{3,5,1,6,2,3,4,1}。

  

  第二種,復雜度比上面那一種要優,但不能處理重復元素。

  先看代碼:

const int N=1e5+7;
struct Node{
  int v,id;
  bool operator < (const Node a)const{
    return v<a.v;}//排序用
}a[N];
int n,rank[N];
int main()
{
  cin>>n;
  for(int i=1;i<=n;i++){
    cin>>a[i].v;
    a[i].id=i;}
  sort(a+1,a+n+1);
  for(int i=1;i<=n;i++)
    rank[a[i].id]=i;
}

  這種方法直接用結構體存儲原本的數列的元素的位置,然后排序以后將他們再重新賦值。那么rank[]就是結構體a[]離散化后的結果。

  舉個栗子:

  v: 3 6 5 10 8

  id:1 2 3 4 5

  排序以后:

  v: 3 5 6 8 10

  id:1 3 2 5 4

  所以離散化以后:

  v: 3 5 6 8 10

  id:1 3 2 5 4

  rk:1 2 3 4 5

  在按原來的順序排列:

  v: 3 6 5 10 8

  rk:1 3 2 5 4

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM