逆序數的幾種求法

2021-08-21 18:51:33 字數 3088 閱讀 6316

什麼叫逆序數

對於某乙個數來說,它的逆序數等於在它之前有多少個比它大的數

對於某乙個序列來說,逆序數等於所有數的逆序數之和 例如

序列      5   1    5   2

逆序數   0   1    0   2

序列的逆序數 1+2=3

來看逆序數的求法

首先將定義乙個結構體,存數列的值和下標,然後按數值從大到小(數值相同按下標從大到小)sort一下

然後建立樹狀陣列,從最大的元素開始,將其標記,即   add(p【i】.id,1)

利用其query(i)查詢當前1----i的和

對於第i大的數,由於之前所有比它大的數已經標記,所以query(i)就是當前數的逆序數

例如  5  6  3  8  2     其排序之後即是      2   3   5   6   8   將求對應的值的逆序數的問題轉化成了求下標對應的逆序數按求逆

1  2  3  4  5                                    5   3   1   2    4

序數的方法,先求下標的逆序數  即:   0 + 1 + 2 + 2 + 1  =   6 ,答案即是序列的逆序數,

換一種思路來看,  為了避免加入順序而導致逆序數的不正確,所以從後面開始逆序,因為已經轉化成下標的逆序

所以只需看下標即可,  5   3   1   2   4  對於4的逆序只有5,在c[5]+1,

對於2的逆序有5,3,在c[5]+1,c[3]+1

其餘類似。。。。。

然後對於3來說的樹狀陣列求1~3的和,即是求以3為逆序數(此例是1,2)的數的個數,

同理對於 i 來求1~i 之間的和,就是來求以 i 為逆序數的數的個數,最後求個總和,也就是所要求的該數列的逆序數。

**:

#include#include#includeusing namespace std;

int c[100010];

typedef struct nodeenode;

node maze[10010];

bool cmp(node u,node v)

return sum;

}int main()

sort(maze+1,maze+n+1,cmp);

int sum=0;

for(i=n;i>=1;i--)

printf("%d\n",sum); }

return 0;

}

也是樹狀陣列,不過要離散化處理

所謂的離散化就是將陣列排個序,例如從小到大排序,

那麼將第一小記做1,第二小記做2,那麼就算是離散化了

(離散,字面意思,分離,散開,分成乙個個的小塊,當然每個塊不能相同)

這個處理的話就是這樣

序列      5   1    5   2

離散化陣列     3   1    3   2

這樣從最小的數開始建立樹狀陣列(標記)

那麼i-query(b【i】)就是當前數的逆序數(i為當前第i個的數,b【i】是當前數是第幾小,

query詢問的是1------i有多少個標記的數(小於等於當前數的數),i-query(b【i】)自然是大於當前數  的數  的個數)

例如例項:maze[i].x:            2   5   7   3   4    排序後為    maze[i].x           2  3   4   5   7         

maze[i].num       1   2   3   4   5                       maze[i].num      1  4   5   2   3    

離散化後為:   maze[i].x                 2    3    4     5    7       按照num的順序走就是:

maze[i].num            1    4     5     2    3                             maze[i].num   1    2    3   4   5 

b[maze[i].num]        1    2     3     4    5                        b[maze[i].num]    1    4    5   2   3

對於這個例子,maze[i].num 從1~n開始遍歷,先add(1),改變字尾和,將比1大的c[i]都加1,

然後add(4),將比4 大的位置都加1

。。。。。以此類推

然後每一次query(b[i]),就代表在i之前有多少比 b[i] 小的數的個數,因為 i 代表b[i] 的位置,即前面有幾個數

所以 i-query(b[i]) ,就代表 b[i]  之前有幾個比它大的數的個數。

補充乙個

離散化三部曲:

1. 陣列 ha 儲存所有存在過的資料,sort排序

2. 對ha陣列進行去重,重複的資料只保留乙個。unique去重(unique函式前提有序)

3. 查詢某個數字離散化之後對應的數字,lower_bound查排名 **

#include#include#include#include#define ll long long

using namespace std;

int n,c[100010];

int lowbit(int x)

void add(int k,int num)}

int query(int k)

return sum;

}typedef struct nodee

node;

node maze[100010];

bool cmp(node u,node v)

void merge_sort(int a, int low, int high)

}void merge(int a, int low, int mid, int high)

}while(i <= mid)

while(j <= high)

for(k = 0, i = low; i <= high; i++, k++)

}

方法四

直接數 的就不寫了

逆序數的幾種求法

求乙個數列的逆序數 逆序對 數列a 1 a 2 a 3 中的任意兩個數a i a j i,如果a i a j 那麼我們就說這兩個數構成了乙個逆序對 逆序數 乙個數列中逆序對的總數 如數列3 5 4 8 2 6 9 5,4 是乙個逆序對,同樣還有 3,2 5,2 4,2 等等 那麼如何求得乙個數列的逆...

逆序數的幾種求法

求乙個數列的逆序數 逆序對 數列a 1 a 2 a 3 中的任意兩個數a i a j i,如果a i a j 那麼我們就說這兩個數構成了乙個逆序對 逆序數 乙個數列中逆序對的總數 如數列3 5 4 8 2 6 9 5,4 是乙個逆序對,同樣還有 3,2 5,2 4,2 等等 那麼如何求得乙個數列的逆...

逆序數的求法

求乙個數列的逆序數 逆序對 數列s 1 a 2 a 3 中的任意兩個數s i s j is j 那麼我們就說這兩個數構成了乙個逆序對 逆序數 乙個數列中逆序對的總數 5,4 是乙個逆序對,同樣還有 3,2 5,2 4,2 等等 那麼如何求得乙個數列的逆序數呢?方法1 乙個乙個的數 最簡單也是最容易想...