// TanosMeanLessMemory.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
 
 
#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <chrono>
#include <iomanip>
#include <string>    
#include <sstream>   
#include <cmath>     
// U
bool IsFinite(double v) {
    return !std::isnan(v) && !std::isinf(v);
}
 
class ThanosMeanLessMemory {
public:
    // --- int[] ---
    static void ThanosIntSortInPlace(std::vector<int>& a) {
        if (a.empty() || a.size() < 2) return;
        std::vector<int> sorted = SortNoExtraCopy(a);
        a = sorted; // Assign the sorted vector back to a
    }
 
private:
    static std::vector<int> SortNoExtraCopy(std::vector<int> seg) {
        int n = seg.size();
        if (n < 2) return seg;
 
        int mn = seg[0], mx = seg[0];
        long long sum = seg[0];
        for (int i = 1; i < n; i++) {
            int v = seg[i];
            if (v < mn) mn = v;
            if (v > mx) mx = v;
            sum += v;
        }
        if (mn == mx) return seg;
 
        double c = static_cast<double>(sum) / n;
 
        int cntL = 0;
        for (int v : seg) if (v <= c) cntL++;
        int cntR = n - cntL;
 
        std::vector<int> left(cntL);
        std::vector<int> right(cntR);
        int iL = 0, iR = 0;
        for (int v : seg) if (v <= c) left[iL++] = v; else right[iR++] = v;
 
        left = SortNoExtraCopy(left);
        right = SortNoExtraCopy(right);
 
        std::vector<int> outArr(n);
        std::copy(left.begin(), left.end(), outArr.begin());
        std::copy(right.begin(), right.end(), outArr.begin() + left.size());
        return outArr;
    }
 
public:
    // --- double[] ---
    static void ThanosDoubleSortInPlace(std::vector<double>& a) {
        if (a.empty() || a.size() < 2) return;
        std::vector<double> sorted = SortDoubleNoExtraCopy(a);
        a = sorted; // Assign the sorted vector back to a
    }
 
private:
    static std::vector<double> SortDoubleNoExtraCopy(std::vector<double> seg) {
        int n = seg.size();
        if (n < 2) return seg;
 
        bool allSame = true;
        for (int i = 1; i < n; i++) if (seg[i] != seg[0]) { allSame = false; break; }
        if (allSame) return seg;
 
        double sum = 0.0;
        int cntFinite = 0;
        for (double v : seg) if (IsFinite(v)) { sum += v; cntFinite++; }
        if (cntFinite == 0) return seg;
 
        double c = sum / cntFinite;
 
        int cntL = 0;
        for (double v : seg)
            if (std::isinf(v) && v < 0 || (IsFinite(v) && v <= c)) cntL++;
        int cntR = n - cntL;
 
        std::vector<double> left(cntL);
        std::vector<double> right(cntR);
        int iL = 0, iR = 0;
        for (double v : seg)
            if (std::isinf(v) && v < 0 || (IsFinite(v) && v <= c)) left[iL++] = v;
            else right[iR++] = v; // +Infinity и NaN здесь
 
        left = SortDoubleNoExtraCopy(left);
        right = SortDoubleNoExtraCopy(right);
 
        std::vector<double> outArr(n);
        std::copy(left.begin(), left.end(), outArr.begin());
        std::copy(right.begin(), right.end(), outArr.begin() + left.size());
        return outArr;
    }
 
public:
    // --- генераторы ---
    static std::vector<double> GenerateDoubleRandomArray(int n, double min, double max) {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_real_distribution<> dis(min, max);
 
        std::vector<double> arr(n);
        for (int i = 0; i < n; i++) arr[i] = dis(gen);
        return arr;
    }
 
    static std::vector<int> GenerateRandomArray(int n, int min, int max) {
        std::random_device rd;
        std::mt19937 gen(rd());
        std::uniform_int_distribution<> dis(min, max);
 
        std::vector<int> arr(n);
        for (int i = 0; i < n; i++) arr[i] = dis(gen);
        return arr;
    }
};
 
template <typename T>
std::string Arr(const std::vector<T>& a) {
    std::string result = "[";
    for (size_t i = 0; i < a.size(); ++i) {
        result += std::to_string(a[i]);
        if (i < a.size() - 1) {
            result += ", ";
        }
    }
    result += "]";
    return result;
}
 
int main() {
    // Консоль в UTF-8 (Implementation depends on the OS and compiler, omitted for brevity)
 
    // int
    std::vector<int> arr = ThanosMeanLessMemory::GenerateRandomArray(1000000, 0, 1000000);
    auto tumbler = std::chrono::high_resolution_clock::now();
 
    // 1) Главный тестовый код
    std::vector<int> t1 = arr; // Copy the vector
    std::cout << "start Main test code watch." << std::endl;
    tumbler = std::chrono::high_resolution_clock::now();
    ThanosMeanLessMemory::ThanosIntSortInPlace(t1);
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << "stop watch." << std::endl;
    std::cout << "Thanos main test code : " << std::fixed << std::setprecision(2)
        << std::chrono::duration<double, std::milli>(end - tumbler).count() << " ms" << std::endl;
    std::cout << "_________" << std::endl;
 
    // 2) std::sort (internal)
    std::vector<int> t2 = arr; // Copy the vector
    std::cout << "start internal std::sort code watch." << std::endl;
    tumbler = std::chrono::high_resolution_clock::now();
    std::sort(t2.begin(), t2.end());
    end = std::chrono::high_resolution_clock::now();
    std::cout << "stop watch." << std::endl;
    std::cout << "std::sort , internal     : " << std::fixed << std::setprecision(2)
        << std::chrono::duration<double, std::milli>(end - tumbler).count() << " ms" << std::endl;
    std::cout << "_________" << std::endl;
 
    // double
    std::vector<double> arrD = ThanosMeanLessMemory::GenerateDoubleRandomArray(1000000, 0.0, 1000000.0);
 
    // 1) Главный тестовый код
    std::vector<double> tD1 = arrD; // Copy the vector
    std::cout << "start Main test double code watch." << std::endl;
    tumbler = std::chrono::high_resolution_clock::now();
    ThanosMeanLessMemory::ThanosDoubleSortInPlace(tD1);
    end = std::chrono::high_resolution_clock::now();
    std::cout << "stop watch." << std::endl;
    std::cout << "Thanos main double test code : " << std::fixed << std::setprecision(2)
        << std::chrono::duration<double, std::milli>(end - tumbler).count() << " ms" << std::endl;
    std::cout << "_________" << std::endl;
 
    // 3) std::sort
    std::vector<double> tD3 = arrD; // Copy the vector
    std::cout << "start internal std::sort double code watch." << std::endl;
    tumbler = std::chrono::high_resolution_clock::now();
    std::sort(tD3.begin(), tD3.end());
    end = std::chrono::high_resolution_clock::now();
    std::cout << "stop watch." << std::endl;
    std::cout << "std::sort , double internal     : " << std::fixed << std::setprecision(2)
        << std::chrono::duration<double, std::milli>(end - tumbler).count() << " ms" << std::endl;
    std::cout << "_________" << std::endl;
 
    return 0;
}
 