求逆序數的兩種重要方法 (51nod逆序數)

2021-09-11 04:07:22 字數 3146 閱讀 1080

利用這個題來了解一下逆序對是神馬

解決逆序數問題有三種方法,但是第一種暴力求解不贊成使用  所以這裡不詳細說明

歸併排序基本思想:將已有序的子串行合併,得到完全有序的序列;即先使每個子串行有序,再使子串行段間有序。

演算法如下:

#include #include int count; 

void merge(int sourcearr,int temparr, int startindex, int midindex, int endindex)

else

temparr[k++] = sourcearr[i++];

}while(i != midindex+1)

temparr[k++] = sourcearr[i++];

while(j != endindex+1)

temparr[k++] = sourcearr[j++];

for(i=startindex; i<=endindex; i++)

sourcearr[i] = temparr[i];}

//內部使用遞迴

void mergesort(int sourcearr, int temparr, int startindex, int endindex)}

int main(int argc, char * ar**)

; int i, b[8];//臨時備用陣列

mergesort(a, b, 0, 7);

for(i=0; i<8; i++)

printf("%d ", a[i]);

printf("\n");

printf("%d\n",count);

return 0;

}

借鑑別人的說法(易懂)

答題思路:

對於乙個序列

50, 10, 20, 30, 70, 40, 80, 60

首先找到他的最大的數,80,將他的位置置1

0    0     0      0      0     0     1     0

前邊沒有資料,即count=0;

第二大數 70  位置置 1

0     0     0     0      1     0     1     0

統計其前的資料count=0;

第三大數60  位置置1

0    0     0     0      1     0      1     1

統計前面的數 count=2;

#include #include #include #include using namespace std;

const int n = 500005;

struct node;

node node[n];

int c[n], reflect[n], n;

bool cmp(const node& a, const node& b)

int lowbit(int x)//對於1位1,2位2,4為4 5,為1 等等,最後乙個不為0的數的2的x次方

void update(int x)}

int getsum(int x)

return sum;}

int main()

sort(node + 1, node + n + 1, cmp); //排序

for (int i = 1; i <= n; ++i) reflect[node[i].pos] = i; //離散化

for (int i = 1; i <= n; ++i) c[i] = 0; //初始化樹狀陣列

long long ans = 0;

for (int i = 1; i <= n; ++i)//對原陣列進行從第乙個往後計算個數

printf("%lld\n", ans);

} return 0;

}

關於樹狀陣列  有幾點解釋

構建&詢問&修改

<1>構建:應該並不存在什麼難度,唯一要考慮的就是如何得到為該數因子中最大的2^x是多少。我自己在想的時候只能想到很複雜的還要預處理的方式,其實巧妙地利用位運算子就可以以o(1)的速度直接得到,至於原因,沒有去考慮,記著就行吧。**:

int lowbit(int x)

<2>求陣列的和:我們注意到,樹狀陣列在求和的時候,相對於普通陣列的優勢就像樹鏈剖分和普通lca一樣。每次我們不需要乙個乙個相加,直接利用當前位置的lowbit值跳轉即可,如**:

int getsum(int now)

int sum=0;

while (now>0) sum+=c[now],now-=lowbit(now);

return sum;

<3>單點修改權值:同樣地,修改也是非常快的,o(log n),假設當前為節點i加上val,如**:

int update(int i,int val) 

最上面的那個鏈結的題解——用樹狀陣列來解決

按照小的數出現順序,把小的數的占用位置刪除 ,每次算位置之前的區間內有多少個比這個數大的數,乙個個的數出來加起來

#include #include #include #include #include #include #include#include#includeusing namespace std;

int a[50005],b[50005],n;

struct uu //結構體記錄 a為輸入的數值,b為數值的位置

d[50005];

int cmp(uu a,uu b) //按照輸入的數值從小到大排序}

int sum(int x) //求區間和,用樹狀陣列時間複雜度為log(n);

long long nixv() // 按照數字出現的順序刪減區間內的數,和為總的逆序對數

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

build();

cout

求逆序數兩種方法 線段樹 歸併排序

題目 hdu 4911 poj 2299 第一反應是暴力掃一遍,時間複雜度o n 2 這在處理10 5的數量級的資料時一定會超時。以下給出兩種將時間複雜度優化至o nlogn 的方法 以hdu 4911為例,求逆序數的模板題 方法1,歸併排序法 在區間 l,r 上,mid l r 1 將兩串已經排好...

求逆序數的幾種方法

求乙個數列的逆序數 逆序對 數列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 等等 那麼如何求得乙個數列的逆...

求素數的兩種解法

檔名 exp1 1.cpp 求素數的個數 include include bool prime int n 判斷正整數n是否是素數 int main for i 3 i n i 2 printf n return 0 檔名 exp1 1 2.cpp 利用快速篩選法求素數的個數 篩法的思想是去除要求範...