利用這個題來了解一下逆序對是神馬
解決逆序數問題有三種方法,但是第一種暴力求解不贊成使用 所以這裡不詳細說明
歸併排序基本思想:將已有序的子串行合併,得到完全有序的序列;即先使每個子串行有序,再使子串行段間有序。
演算法如下:
#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,將他的位置置10 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 利用快速篩選法求素數的個數 篩法的思想是去除要求範...