Помогите сократить время работы кода при максимальных значениях

#include <iostream>
#include <vector>
#include <climits> 

using namespace std;

int main() {
    int n, k;
    cin >> n >> k;
    
    int arr[20][10000];

    for (int i = 0; i < k; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> arr[i][j];
        }
    }
    int otjm = 0;
 
    for (int i = 0; i < k; ++i) {
       
        for (int j = 1; j < n; ++j) {
            int count = 0;
            for (int m = 0; m < j; ++m) {
                if (arr[i][m] > arr[i][j]) {
                    count++;
                }
            }
            otjm += count;
        }
    }

    cout << otjm;
   

    return 0;
}

(k - количество строк до 20, n - столбцов до 10000)

суть в программы в том, что для каждого числа каждой строки нужно найти количество чисел слева, больше текущего и сложить все значения. выдаёт ошибку Time limit exceeded для максимальных значений. Как можно оптимизировать это? пример теста:

5 2

1 5 2 4 3

2 3 1 5 4

вывод: 7


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Время пришло написать подсчёт инверсий за NlogN через сортировку слиянием. Это обычный merge_sort с одной особенностью: каждый раз когда элемент из второго массива "обгоняет" элементы из первого массива и вставляется в результат, количество "обогнанных" элементов накапливается в счётчике инверсий. Можно показать что в итоге получится суммарное количество инверсий для всех элементов массива.

#include <iostream>
#include <vector>

using Array = std::vector<int>;

auto merge(const Array &a, const Array &b, Array &c) {
    size_t n_invs = 0;
    auto m = a.size();
    decltype(m) i = 0;
    auto n = b.size();
    decltype(n) j = 0;
    decltype(c.size()) k = 0;
    while (i < m && j < n) {
        if (a[i] <= b[j]) {
            c[k++] = a[i++];
        } else {
            c[k++] = b[j++];
            n_invs += m - i;
        }
    }
    for (; i < m; ++i) {
        c[k++] = a[i];
    }
    for (; j < n; ++j) {
        c[k++] = b[j];
    }
    return n_invs;
}

size_t merge_sort(Array &a) {
    auto i = a.size() >> 1;
    if (i == 0) {
        return 0;
    }
    Array lo(a.begin(), a.begin() + i         );
    Array hi(           a.begin() + i, a.end());
    auto n_invs = merge_sort(lo) + merge_sort(hi);
    return n_invs + merge(lo, hi, a);
}

int main(){
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, k;
    std::cin >> n >> k;
    Array line(n);

    size_t answer = 0;
    for (int i = 0; i < k; ++i) {
        for (int j = 0; j < n; ++j) {
            std::cin >> line[j];
        }
        answer += merge_sort(line);
    }
    std::cout << answer << '\n';
}
→ Ссылка