#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <cassert>

template <
        class Container,
        class Operation,
        class T = typename Container::value_type,
        class size_type = typename Container::size_type>
std::vector<T> sliding_window(const Container & input, size_type m, const Operation & operation) {
    size_type input_size = input.size();
    if (input_size < m)
        return {};
    std::vector<T> left_partial, right_partial = {input.back()};
    left_partial.reserve(input_size);
    right_partial.reserve(input_size + 1);
    size_type idx = 0;
    {
        auto direct_it = input.begin();
        auto reverse_it = input.rbegin();
        for (; direct_it != input.end(); ++direct_it, ++reverse_it, ++idx) {
            left_partial.push_back(idx % m
                               ? operation(left_partial[idx - 1], *direct_it)
                               : *direct_it);
            right_partial.push_back((input_size - idx) % m
                                ? operation(right_partial[idx], *reverse_it)
                                : *reverse_it
            );
        }
    }

    std::vector<T> result;
    size_t result_size = input_size - m + 1;
    result.reserve(result_size);
    for (size_type i = 0; i < result_size; ++i) {
        auto & left_part = right_partial[input_size - i];
        auto & right_part = left_partial[i + m - 1];

        result.push_back(i % m
                         ? operation(left_part, right_part)
                         : left_part);
    }
    return result;
}

int main(){
    std::vector<int> v = {3, 10, 11, 10, 0, 0, 0, 1, 2, 3, 2};
    auto result_max = sliding_window(v, 3, [] (int x, int y) {return std::max(x, y);});
    assert((result_max == decltype(result_max){11, 11, 11, 10, 0, 1, 2, 3, 3}));

    auto result_sum = sliding_window(v, 3, [] (int x, int y) {return x + y;});
    assert((result_sum == decltype(result_sum){24, 31, 21, 10, 0, 1, 3, 6, 7}));
    return 0;
}


