1. 程式人生 > >poj 2299 Ultra-QuickSort

poj 2299 Ultra-QuickSort

n) pri center col 網上 namespace str 屬於 序列

歸並排序求逆序對

題目大意

給你多個序列,讓你求出每個序列中逆序對的數量。

輸入:每組數據以一個數 n 開頭,以下n行,每行一個數字,代表這個序列;

輸出:對於輸出對應該組數據的逆序對的數量;

順便在此吐槽一下翻譯器,翻譯了一頓我啥都看不懂(都懷疑自己是不是中國人了),幸虧自己還能看懂點英語啊。

這個題是機房裏一位小夥伴問我我才做的,蒟蒻的我剛開始居然想要雙重循環(類似於冒泡排序的方法)來做,看完數據範圍之後就放棄了;

然後想到了逆序對是使用歸並排序來做的,所以就自己手碼了一個歸並排序;;可能有的小夥伴還不知道歸並排序的思想,所以看了一晚上歸並排序的蒟蒻——我,就來給小夥伴們介紹一下吧!

歸並排序:

nlog(n)的穩定算法(可用於求逆序對的個數)

應用方法:

二分(所以又叫二路歸並)+遞歸;

為什麽使用遞歸?

answer:要使用歸並排序首先就要將數據分解,一直分解到每一個單位,然後就是進行合並了;

如何合並?

answer:比較a[i]和a[j]的大小(其中a[i]屬於左區間,a[j]屬於右區間,其實就是將左右區間合並、並排序),若a[i]<a[j],則將a[i]復制到r[k]中,然後將r和k都加1,否則將a[j]復制到r[k]中,將r,k加1,最後再將r[k]移動到a[i]中,然後繼續合並;

如何求逆序對?

answer:

下面就是 歸並排序求逆序對 的過程==

技術分享圖片
 1 #include<cstdio>
 2 using namespace std;
 3 const int maxn=5e5+5;
 4 int a[maxn],r[maxn],n;//r[]是輔助用的; 
 5 long long ans;//ans作為全局變量記錄每次逆序對的數量;
 6 //記得ans要開long long,否則WAWAWA
 7 void msort(int s,int t){
 8     if(s==t) return;
 9     int mid=(s+t)>>1;//二進制下右移一位,相當於 /2 ,但是速度更快! 
10     msort(s,mid),msort(mid+1
,t);//遞歸的體現 11 int i=s,j=mid+1,k=s; 12 while(i<=mid&&j<=t) 13 if(a[i]<=a[j]) r[k]=a[i],i++,k++; 14 else r[k]=a[j],j++,k++,ans+=mid-i+1; 15 //ans的計算是最神奇的地方,不過動動腦子,畫個圖啥的也是可以想出來的 16 while(i<=mid) r[k]=a[i],i++,k++; 17 while(j<=t) r[k]=a[j],j++,k++; 18 for(int i=s;i<=t;i++) a[i]=r[i];//每次要更新的是 a[]數組!! 19 } 20 int main(){ 21 while(1){//來一個無限的循環== 22 scanf("%d",&n); 23 if(!n) return 0;//(!n相當於n==0,當然速度也是快一點的啦!)n=0就直接結束程序; 24 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 25 msort(1,n); 26 printf("%lld\n",ans); 27 ans=0;//註意:ans每次都需要清0; 28 } 29 }
poj2299

--------------------------------------------------下方高能--------------------------------------------

其實只是一個實例,解釋一下ans是如何求出來的啦

a[i] mid=4 a[j]

3 4 7 9 1 5 8 10

首先將右區間的 1 取出,放到r[k]中,此時 1 是比每個a[i]中的元素都小,也就是說此時i的指針指向 a[1] 的位置,此刻得到的逆序對的數量為 4 ; r[k]= 1 ;

然後再將a[i]a[j]比較(直到a[i]<a[j]),a[i]<a[j] a[i]的元素放到r[k]中; r[k]= 1 3 4;現在a[j]>a[i], i 指向 a[3] 的位置,將5 放到 r[k] 中,得到的逆序對數量為 2 ; r[k]= 1 3 4 5

以此類推,直到進行完歸並排序,每次合並都會求出逆序對的數目,即 mid-i+1 ,最後每次將 ans 加上 mid-i+1即可得到最後的答案;

技術分享圖片

其實求逆序對呢,還可以用線段樹,不過對於如此蒟的蒟蒻我,還是算了吧,有興趣的小夥伴也可以自己從網上搜著看一下,蒟蒻在此就不介紹給大家了(我也不會啊)

poj 2299 Ultra-QuickSort