歸併排序 模板題+快讀
阿新 • • 發佈:2020-10-29
歸併排序,就是將兩個有序的子序列進行排序。具體參考https://www.cnblogs.com/chengxiao/p/6194356.html。
題目描述
貓貓 TOM 和小老鼠 JERRY 最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。
最近,TOM 老貓查閱到一個人類稱之為“逆序對”的東西,這東西是這樣定義的:對於給定的一段正整數序列,逆序對就是序列中 ai>aja_i>a_jai>aj 且 i<ji<ji<j 的有序對。知道這概念後,他們就比賽誰先算出給定的一段正整數序列中逆序對的數目。注意序列中可能有重複數字。
Update:資料已加強。
輸入格式
第一行,一個數 nnn,表示序列中有 nnn個數。
第二行 nnn 個數,表示給定的序列。序列中每個數字不超過 10910^9109。
輸出格式
輸出序列中逆序對的數目。
輸入輸出樣例
輸入 #16 5 4 2 6 3 1輸出 #1
11
說明/提示
對於 25%25\%25% 的資料,n≤2500n \leq 2500n≤2500
對於 50%50\%50% 的資料,n≤4×104n \leq 4 \times 10^4n≤4×104。
對於所有資料,n≤5×105n \leq 5 \times 10^5n≤5×105
請使用較快的輸入輸出
應該不會 O(n2)O(n^2)O(n2) 過 50 萬吧 by chen_zhe
題解:
#include<bits/stdc++.h> using namespace std; int n; int a[500005],s[500005]; long long int ans; inline int read(){ char ch=getchar(); int f=1; int x=0; while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } void msort(int l,int r){ if(l==r)return ; int mid=(l+r)>>1; msort(l,mid); msort(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid&&j<=r){ if(a[i]<=a[j])s[k++]=a[i++]; else{ s[k++]=a[j++]; ans+=mid-i+1; } } while(i<=mid){ s[k++]=a[i++]; } while(j<=r)s[k++]=a[j++]; for(int i=l;i<=r;i++)a[i]=s[i]; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)a[i]=read(); msort(1,n); printf("%lld\n",ans); }