This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "ds/circular_deque.hpp"Circular Deque is a fixed-size or dynamically-sized double-ended queue implemented using a circular buffer. Provides efficient push/pop operations at both ends in $\mathcal O(1)$ time.
CircularDeque<T, N>()
N
DynamicCircularDeque<T>()
template<class... Ts> T &emplace_front(Ts &&...xs)
template<class... Ts> T &emplace_back(Ts &&...xs)
T &push_front(T x) or T &push_back(T x)
void pop_front() or void pop_back()
T &front() or T &back()
T &operator[](size_t i)
i
size_t size() or bool empty()
void clear()
void reserve(int n) (DynamicCircularDeque only)
n elements#pragma once
template<class T, size_t N> struct CircularDeque {
using value_type = T;
using reference = T &;
using const_reference = const T &;
using size_type = size_t;
size_t fr = 0, bk = 0;
array<T, N> data;
template<class... Ts> T &emplace_front(Ts &&...xs) {
fr = (fr + N - 1) % N;
return data[fr] = T(forward<Ts>(xs)...);
}
template<class... Ts> T &emplace_back(Ts &&...xs) {
size_t tmp = exchange(bk, (bk + 1) % N);
return data[tmp] = T(forward<Ts>(xs)...);
}
T &push_front(T x) { return emplace_front(move(x)); }
T &push_back(T x) { return emplace_back(move(x)); }
void pop_front() { fr = (fr + 1) % N; }
void pop_back() { bk = (bk + N - 1) % N; }
T &front() { return data[fr]; }
T &back() { return data[(bk + N - 1) % N]; }
const T &front() const { return data[fr]; }
const T &back() const { return data[(bk + N - 1) % N]; }
T &operator[](size_t i) { return data[(fr + i) % N]; }
const T &operator[](size_t i) const { return data[(fr + i) % N]; }
size_t size() const { return (bk - fr + N) % N; }
bool empty() const { return bk == fr; }
void clear() { fr = bk = 0, data[0] = T(); }
};
template<class T> struct DynamicCircularDeque {
using value_type = T;
using reference = T &;
using const_reference = const T &;
using size_type = size_t;
size_t fr = 0, bk = 0, cap = 8;
vector<T> data;
DynamicCircularDeque() : data(cap) {}
template<class... Ts> T &emplace_front(Ts &&...xs) {
if (size() + 1 == cap) realloc(cap + 1);
fr = (fr + cap - 1) & (cap - 1);
return data[fr] = T(forward<Ts>(xs)...);
}
template<class... Ts> T &emplace_back(Ts &&...xs) {
if (size() + 1 == cap) realloc(cap + 1);
size_t tmp = exchange(bk, (bk + 1) & (cap - 1));
return data[tmp] = T(forward<Ts>(xs)...);
}
T &push_front(T x) { return emplace_front(move(x)); }
T &push_back(T x) { return emplace_back(move(x)); }
void pop_front() { fr = (fr + 1) & (cap - 1); }
void pop_back() { bk = (bk + cap - 1) & (cap - 1); }
T &front() { return data[fr]; }
T &back() { return data[(bk + cap - 1) & (cap - 1)]; }
const T &front() const { return data[fr]; }
const T &back() const { return data[(bk + cap - 1) & (cap - 1)]; }
T &operator[](size_t i) { return data[(fr + i) & (cap - 1)]; }
const T &operator[](size_t i) const { return data[(fr + i) & (cap - 1)]; }
size_t size() const { return (bk - fr + cap) & (cap - 1); }
bool empty() const { return bk == fr; }
void clear() { fr = bk = 0, data[0] = T(); }
void reserve(int n) { realloc(n); }
private:
void realloc(size_t n) {
while (cap < n) cap *= 2;
vector<T> d(cap);
size_t sz = size();
for (size_t i = 0; i < sz; i++) d[i] = move(data[(fr + i) & (cap - 1)]);
fr = 0, bk = sz, data.swap(d);
}
};
#line 2 "ds/circular_deque.hpp"
template<class T, size_t N> struct CircularDeque {
using value_type = T;
using reference = T &;
using const_reference = const T &;
using size_type = size_t;
size_t fr = 0, bk = 0;
array<T, N> data;
template<class... Ts> T &emplace_front(Ts &&...xs) {
fr = (fr + N - 1) % N;
return data[fr] = T(forward<Ts>(xs)...);
}
template<class... Ts> T &emplace_back(Ts &&...xs) {
size_t tmp = exchange(bk, (bk + 1) % N);
return data[tmp] = T(forward<Ts>(xs)...);
}
T &push_front(T x) { return emplace_front(move(x)); }
T &push_back(T x) { return emplace_back(move(x)); }
void pop_front() { fr = (fr + 1) % N; }
void pop_back() { bk = (bk + N - 1) % N; }
T &front() { return data[fr]; }
T &back() { return data[(bk + N - 1) % N]; }
const T &front() const { return data[fr]; }
const T &back() const { return data[(bk + N - 1) % N]; }
T &operator[](size_t i) { return data[(fr + i) % N]; }
const T &operator[](size_t i) const { return data[(fr + i) % N]; }
size_t size() const { return (bk - fr + N) % N; }
bool empty() const { return bk == fr; }
void clear() { fr = bk = 0, data[0] = T(); }
};
template<class T> struct DynamicCircularDeque {
using value_type = T;
using reference = T &;
using const_reference = const T &;
using size_type = size_t;
size_t fr = 0, bk = 0, cap = 8;
vector<T> data;
DynamicCircularDeque() : data(cap) {}
template<class... Ts> T &emplace_front(Ts &&...xs) {
if (size() + 1 == cap) realloc(cap + 1);
fr = (fr + cap - 1) & (cap - 1);
return data[fr] = T(forward<Ts>(xs)...);
}
template<class... Ts> T &emplace_back(Ts &&...xs) {
if (size() + 1 == cap) realloc(cap + 1);
size_t tmp = exchange(bk, (bk + 1) & (cap - 1));
return data[tmp] = T(forward<Ts>(xs)...);
}
T &push_front(T x) { return emplace_front(move(x)); }
T &push_back(T x) { return emplace_back(move(x)); }
void pop_front() { fr = (fr + 1) & (cap - 1); }
void pop_back() { bk = (bk + cap - 1) & (cap - 1); }
T &front() { return data[fr]; }
T &back() { return data[(bk + cap - 1) & (cap - 1)]; }
const T &front() const { return data[fr]; }
const T &back() const { return data[(bk + cap - 1) & (cap - 1)]; }
T &operator[](size_t i) { return data[(fr + i) & (cap - 1)]; }
const T &operator[](size_t i) const { return data[(fr + i) & (cap - 1)]; }
size_t size() const { return (bk - fr + cap) & (cap - 1); }
bool empty() const { return bk == fr; }
void clear() { fr = bk = 0, data[0] = T(); }
void reserve(int n) { realloc(n); }
private:
void realloc(size_t n) {
while (cap < n) cap *= 2;
vector<T> d(cap);
size_t sz = size();
for (size_t i = 0; i < sz; i++) d[i] = move(data[(fr + i) & (cap - 1)]);
fr = 0, bk = sz, data.swap(d);
}
};