# 逆序对的数量 - 归并排序

# C++ 中 signed main 和 int main 的区别

# C 语言中 int main (int argc, char *argv []) 的两个参数的详解

#include <iostream>

using namespace std;

typedef long long LL;

const int N = 1e6 + 10;

int n;
int q[N], tmp[N];

LL merge_sort(int l, int r){
    if(l >= r) return 0;
    int mid = l + r >> 1;
    LL res = merge_sort(l, mid) + merge_sort(mid + 1, r);

    int k = 0, i = l, j = mid + 1;
    while(i <= mid && j <= r)
        if(q[i] <= q[j]) tmp[k++] = q[i++];
        else{
        tmp[k++] = q[j++];
        res += mid - i + 1;
        }
    while(i <= mid) tmp[k++] = q[i++];
    while(j <= r) tmp[k++] = q[j++];

    for(int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];
    return res;
}

signed main(){
    cin >> n;
    for(int i = 0; i < n; i++) cin >> q[i];
    
    cout << merge_sort(0, n - 1) << endl;
    
    return 0;
}

# 为什么是 mid - i + 1?

数组 a 中的 i ~ mid 的数组是递增数组, 触发条件是 a [i] > a [j],所以 i ~ mid 中的数字都比当前 a [j] 大,所以左边 i ~ mid 的数组中有 mid - i + 1 个数比 a [j] 大

//分治思想就是把一个大问题分解成互不相关的小问题

//5 * 10^9因为会大于int的最大值 所以用longlong来存

#include <iostream>

using namespace std;

typedef long long LL;
//预处理 把下面所有LL替换成 long long

//#define 就是宏定义 typedef 就是类型的宏定义

const int N = 1e6 + 10;

int n;
int q[N], tmp[N];

LL merge_sort(int l, int r){
    if(l >= r) return 0;
    //归并排序中 这里的 >= 可以写成 == 但是快排不可以 因为快排 可能没有r r可能小于l
    
    int mid = l + r >> 1;
    //取中间值 因为这里 + 号的优先级比 >> 的优先级要高 所以可以不用加括号
    
    LL res = merge_sort(l, mid) + merge_sort(mid + 1, r);
    
    
    //归并的过程
    int k = 0, i = l, j = mid + 1;
    while(i <= mid && j <= r)
        if(q[i] <= q[j]) tmp[k++] = q[i++];
        else{
            tmp[k++] = q[j++];
            res += mid - i + 1;
        }
    // 扫尾
    
    while(i <= mid) tmp[k++] = q[i++];
    while(j <= r) tmp[k++] = q[j++];
    
    
    for(int i = l, j = 0; i <= r; i++, j++) q[i] = tmp[j];
    
    return res;
}

signed main(){
    cin >> n;
    for(int i = 0; i < n; i++) cin >> q[i];
    
    cout << merge_sort(0, n - 1) << endl;
    
    
    return 0;
}