232-aka-pretty-pi 2024. 8. 23. 21:48
template <typename T, typename F>
struct SlidingDeque {
  F func;
  std::vector<T> head;
  std::vector<T> tail;
  std::vector<T> fhead;
  std::vector<T> ftail;

  SlidingDeque(const F& _func = F {}) : func(_func) {
    void(0);
  }

  [[nodiscard]] int size() const {
    return int(head.size()) + int(tail.size());
  }

  [[nodiscard]] bool empty() const {
    return size() == 0;
  }

  [[nodiscard]] const T& operator [] (int index) const {
    assert(0 <= index && index < size());
    return (index < int(head.size()) ? head[int(head.size()) - 1 - index] : tail[index - int(head.size())]);
  }

  [[nodiscard]] const T& front() const {
    assert(!empty());
    return head.empty() ? tail.front() : head.back();
  }

  [[nodiscard]] const T& back() const {
    assert(!empty());
    return tail.empty() ? head.front() : tail.back();
  }

  [[nodiscard]] T get() const {
    if (!fhead.empty() && !ftail.empty()) {
      return func(fhead.back(), ftail.back());
    } else if (!fhead.empty()) {
      return fhead.back();
    } else if (!ftail.empty()) {
      return ftail.back();
    } else {
      assert(false);
    }
  }

  void pushFront(const T& x) {
    const T nw = (head.empty() ? x : func(x, fhead.back()));
    head.push_back(x);
    fhead.push_back(std::move(nw));
  }

  void pushBack(const T& x) {
    const T nw = (tail.empty() ? x : func(ftail.back(), x));
    tail.push_back(x);
    ftail.push_back(std::move(nw));
  }

  void transportToHead() {
    head.insert(head.begin(), tail.rbegin() + int(tail.size()) / 2, tail.rend());
    tail.erase(tail.begin(), tail.end() - int(tail.size()) / 2);
    ftail = {};
    std::partial_sum(head.begin(), head.end(), std::back_inserter(fhead), [&](const T& a, const T& b) {
      return func(b, a);
    });
    std::partial_sum(tail.begin(), tail.end(), std::back_inserter(ftail), func);
  }

  void transportToTail() {
    tail.insert(tail.begin(), head.rbegin() + int(head.size()) / 2, head.rend());
    head.erase(head.begin(), head.end() - int(head.size()) / 2);
    fhead = {};
    std::partial_sum(head.begin(), head.end(), std::back_inserter(fhead), [&](const T& a, const T& b) {
      return func(b, a);
    });
    std::partial_sum(tail.begin(), tail.end(), std::back_inserter(ftail), func);
  }

  void popFront() {
    assert(!empty());
    if (head.empty()) {
      transportToHead();
    }
    head.pop_back();
    fhead.pop_back();
  }

  void popBack() {
    assert(!empty());
    if (tail.empty()) {
      transportToTail();
    }
    tail.pop_back();
    ftail.pop_back();
  }

  void clear() {
    head = {};
    tail = {};
    fhead = {};
    ftail = {};
  }
};