Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

The Number of Inversions

For a given sequence $A = \{a_0, a_1, ... a_{n-1}\}$, the number of pairs $(i, j)$ where $a_i > a_j$ and $i < j$, is called the number of inversions. The number of inversions is equal to the number of swaps of Bubble Sort defined in the following program:

bubbleSort(A)
cnt = 0 // the number of inversions
for i = 0 to A.length-1
for j = A.length-1 downto i+1
if A[j] < A[j-1]
swap(A[j], A[j-1])
cnt++

return cnt

For the given sequence $A$, print the number of inversions of $A$. Note that you should not use the above program, which brings Time Limit Exceeded.

Input

In the first line, an integer $n$, the number of elements in $A$, is given. In the second line, the elements $a_i$ ($i = 0, 1, .. n-1$) are given separated by space characters.

output

Print the number of inversions in a line.

Constraints

$ 1 \leq n \leq 200,000$

$ 0 \leq a_i \leq 10^9$

$a_i$ are all different

Sample Input 1

5
3 5 2 1 4

Sample Output 1

6

Sample Input 2

3
3 1 2

Sample Output 2

2

Solution in C# (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Linq;
using static System.Math;
 
class Program{
    static void Main(){
        int n = int.Parse(Console.ReadLine());
        int[] a = Console.ReadLine().Split().Select(int.Parse).ToArray();
        Console.WriteLine(InvNum.InversionNumber(a));
    }
}
 
static class InvNum
{
    /* 配列aの転倒数を求める */
    public static long InversionNumber(long[] a)
    {
        int n = a.Length;
        SortedSet<long> s = new SortedSet<long>();
        foreach (var i in a) s.Add(i);
        long[] sorted_a = s.ToArray();
        RSQ1 rsq = new RSQ1(n);
        long[] t2 = new long[n];
        for (int j = 0; j < n; j++)
        {
            t2[j] = rsq.Query(0, BS.Search(sorted_a, a[j]) + 1);
            rsq[BS.Search(sorted_a, a[j])] += 1;
        }
        long InvN = 0;
        for (int j = 0; j < n; j++)
            InvN += j - t2[j];
        return InvN;
    }
    public static long InversionNumber(int[] a)
    {
        long[] a2 = a.Select(s => (long)s).ToArray();
        return InversionNumber(a2);
    }
}
 
struct RSQ1
{
    private int n;
    private long[] dat;
    public int Length { get; private set; }
    public long this[int i]
    {
        get
        {
            if (i < 0 || i >= this.Length)
                throw new IndexOutOfRangeException();
            return dat[i + n - 1];
        }
        set { this.Update(i, value); }
    }
 
    /* nを要素数として、すべて0で初期化 */
    public RSQ1(int n)
    {
        Length = n;
        this.n = 1;
        while (this.n < n) this.n *= 2;
        dat = new long[2 * this.n];
    }
 
    /* k番目(0-indexed)をaに変更 */
    public void Update(int k, long a)
    {
        k += n - 1;
        dat[k] = a;
        while (k > 0)
        {
            k = (k - 1) / 2;
            dat[k] = dat[k * 2 + 1] + dat[k * 2 + 2];
        }
    }
 
    private long Query_(int a, int b, int k, int l, int r)
    {
        if (r <= a || b <= l) return 0;
        if (a <= l && r <= b) return dat[k];
        long v1 = Query_(a, b, k * 2 + 1, l, (l + r) / 2);
        long v2 = Query_(a, b, k * 2 + 2, (l + r) / 2, r);
        return v1 + v2;
    }
 
    /* [a,b)の和を求める */
    public long Query(int a, int b)
    {
        return Query_(a, b, 0, 0, n);
    }
}

class BS
{
    /* 昇順なarrayからsを二分探索で探し、indexを返す(複数あればそのうちの1つ) */
    public static int Search(long[] array, long s)
    {
        int l = 0;
        int r = array.Length - 1;
        while (l != r)
        {
            int m = l + (r - l) / 2;
            if (array[m] == s) return m;
            if (array[m] < s) l = m + 1;
            if (array[m] > s) r = m - 1;
        }
        return l;
    }
    public static int Search(int[] array, int s)
    {
        long[] lis = array.Select(n => (long)n).ToArray();
        return Search(lis, s);
    }
    public static int Search(List<int> list, int s)
    {
        int[] array = list.ToArray();
        return Search(array, s);
    }
    public static int Search(List<long> list, long s)
    {
        long[] array = list.ToArray();
        return Search(array, s);
    }

    /* 単調非減少なarrayから、array[i] >= kなる最小のiを返す(なければn) */
    public static int Lower_Bound(long[] array, long k)
    {
        int l = -1;
        int r = array.Length;
        while (r - l > 1)
        {
            int m = (l + r) / 2;
            if (array[m] >= k) r = m;
            else l = m;
        }
        return r;
    }
    public static int Lower_Bound(int[] array, int k)
    {
        long[] a = array.Select(s => (long)s).ToArray();
        return Lower_Bound(a, k);
    }
    public static int Lower_Bound(List<long> list, long k)
    {
        long[] a = list.ToArray();
        return Lower_Bound(a, k);
    }
    public static int Lower_Bound(List<int> list, int k)
    {
        int[] a = list.ToArray();
        return Lower_Bound(a, k);
    }
}