1. 程式人生 > 實用技巧 >歸併排序 模板題+快讀

歸併排序 模板題+快讀

歸併排序,就是將兩個有序的子序列進行排序。具體參考https://www.cnblogs.com/chengxiao/p/6194356.html。

題目描述

貓貓 TOM 和小老鼠 JERRY 最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。

最近,TOM 老貓查閱到一個人類稱之為“逆序對”的東西,這東西是這樣定義的:對於給定的一段正整數序列,逆序對就是序列中 ai>aja_i>a_jai>aji<ji<ji<j 的有序對。知道這概念後,他們就比賽誰先算出給定的一段正整數序列中逆序對的數目。注意序列中可能有重複數字。

Update:資料已加強。

輸入格式

第一行,一個數 nnn,表示序列中有 nnn個數。

第二行 nnn 個數,表示給定的序列。序列中每個數字不超過 10910^9109。

輸出格式

輸出序列中逆序對的數目。

輸入輸出樣例

輸入 #1
6
5 4 2 6 3 1
輸出 #1
11

說明/提示

對於 25%25\%25% 的資料,n≤2500n \leq 2500n2500

對於 50%50\%50% 的資料,n≤4×104n \leq 4 \times 10^4n4×104。

對於所有資料,n≤5×105n \leq 5 \times 10^5n5×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); }