pragma once
 
#include <vector>
#include <math.h>
 
template<class It>
class IteratorRange {
 public:
  IteratorRange(It b, It e) : begin_(b), end_(e), size_(std::distance(b, e)) {}
 
  It begin() const {
    return begin_;
  }
 
  It end() const {
    return end_;
  }
 
  size_t size() const {
    return size_;
  }
 private:
  It begin_, end_;
  size_t size_;
};
 
template<typename It>
class Slicer {
 public:
  Slicer(It b, It e, int page_size) : size_(ceil(std::distance(b, e) / static_cast<double>(page_size))) {
    auto beg = b;
    for (; b != e; ++b) {
      if (std::distance(beg, b)+1 == page_size) {
        pages_.push_back(IteratorRange<It>(beg, ++b));
        beg = b;
      }
      if (std::distance(beg, e) < page_size) {
        if (std::distance(beg, e) > 0) {
          pages_.push_back(IteratorRange<It>(beg, e));
        }
        break;
      }
    }
  }
 
  auto begin() const {
    return pages_.begin();
  }
 
  auto end() const {
    return pages_.end();
  }
 
  size_t size() const {
    return size_;
  }
 
 private:
  std::vector<IteratorRange<It>> pages_;
  size_t size_;
};
 
template<typename C>
auto Slice(C &c, size_t page_size) {
  return Slicer<typename C::iterator>(c.begin(), c.end(), page_size);
}
 
template<typename C>
auto Slice(const C &c, size_t page_size) {
  return Slicer<typename C::const_iterator>(c.begin(), c.end(), page_size);
}
 
template<>
auto Slice(const IteratorRange<std::vector<int>::iterator> &c, size_t page_size) {
  return Slicer<std::vector<int>::iterator>(c.begin(), c.end(), page_size);
}