m1une's library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: Inversion Count
(algo/sequence/inversion_count.hpp)

Overview

Calculates the number of inversions in a sequence. An inversion is a pair of indices (i, j) such that i < j and a[i] > a[j].

The implementation uses merge sort and does not require coordinate compression.

The return type is long long because a sequence of size $N$ can have $N(N-1)/2$ inversions.

Template Parameters

Methods

Method Description Complexity
long long inversion_count(std::vector<T> a) Returns the total number of inversions. The argument is taken by value. Use std::move(a) if you no longer need the original array to avoid an $O(N)$ copy. $O(N \log N)$ time, $O(N)$ space

Example

#include "algo/sequence/inversion_count.hpp"
#include <iostream>
#include <vector>

int main() {
    std::vector<int> a = {2, 4, 1, 3, 5};

    const long long inversions = m1une::algo::inversion_count(a);

    // The inversions are:
    // (2, 1) -> indices 0 and 2
    // (4, 1) -> indices 1 and 2
    // (4, 3) -> indices 1 and 3
    std::cout << "Inversions: " << inversions << "\n"; // Output: 3

    // To avoid copying the array if you don't need it afterward:
    // long long fast_invs = m1une::algo::inversion_count(std::move(a));

    return 0;
}

Required by

Verified with

Code

#ifndef M1UNE_ALGO_SEQUENCE_INVERSION_COUNT_HPP
#define M1UNE_ALGO_SEQUENCE_INVERSION_COUNT_HPP 1

#include <vector>

namespace m1une {
namespace algo {

// Returns the number of pairs (i, j) with i < j and a[i] > a[j].
// The vector is taken by value because merge sort rearranges it.
template <typename T>
long long inversion_count(std::vector<T> a) {
    const int n = int(a.size());
    std::vector<T> temp = a;

    auto merge_sort = [&](auto& self, int l, int r) -> long long {
        if (r - l <= 1) return 0;

        const int m = l + (r - l) / 2;
        long long inv = self(self, l, m) + self(self, m, r);

        int i = l;
        int j = m;
        int k = l;
        while (i < m && j < r) {
            if (!(a[j] < a[i])) {
                temp[k++] = a[i++];
            } else {
                temp[k++] = a[j++];
                inv += m - i;
            }
        }

        while (i < m) temp[k++] = a[i++];
        while (j < r) temp[k++] = a[j++];

        for (int p = l; p < r; ++p) {
            a[p] = temp[p];
        }

        return inv;
    };

    return merge_sort(merge_sort, 0, n);
}

}  // namespace algo
}  // namespace m1une

#endif  // M1UNE_ALGO_SEQUENCE_INVERSION_COUNT_HPP
#line 1 "algo/sequence/inversion_count.hpp"



#include <vector>

namespace m1une {
namespace algo {

// Returns the number of pairs (i, j) with i < j and a[i] > a[j].
// The vector is taken by value because merge sort rearranges it.
template <typename T>
long long inversion_count(std::vector<T> a) {
    const int n = int(a.size());
    std::vector<T> temp = a;

    auto merge_sort = [&](auto& self, int l, int r) -> long long {
        if (r - l <= 1) return 0;

        const int m = l + (r - l) / 2;
        long long inv = self(self, l, m) + self(self, m, r);

        int i = l;
        int j = m;
        int k = l;
        while (i < m && j < r) {
            if (!(a[j] < a[i])) {
                temp[k++] = a[i++];
            } else {
                temp[k++] = a[j++];
                inv += m - i;
            }
        }

        while (i < m) temp[k++] = a[i++];
        while (j < r) temp[k++] = a[j++];

        for (int p = l; p < r; ++p) {
            a[p] = temp[p];
        }

        return inv;
    };

    return merge_sort(merge_sort, 0, n);
}

}  // namespace algo
}  // namespace m1une
Back to top page