This documentation is automatically generated by competitive-verifier/competitive-verifier
#include "structure/others/queue-operate-aggregation.hpp"
半群の要素列 $A$ に対して以下の操作を効率的に行います。
QueueOperateAggregation< T, F >(F f)
二項演算 $f$ で定義される型 T
の半群の要素列 $A$ を、空の列で初期化します。
bool empty() const
$A$ が空のとき true
、空でないとき false
を返します。
size_t size() const
$A$ の要素数を返します。
T all_prod() const
$A$ 全体を $f$ で集約した値を返します。
void push(const T &x)
$A$ の末尾に $x$ を追加します。
void pop()
$A$ の先頭の要素を削除します。
template<typename T, typename F>
QueueOperateAggregation<T, F> get_queue_operate_aggregation(const F &f)
型 T
、二項演算 f
の半群に対応する QueueOperateAggregation
を返すヘルパー関数です。
auto que = get_queue_operate_aggregation< T >(f);
template <typename T, typename F>
struct QueueOperateAggregation {
private:
struct Node {
T val, sum;
Node(const T& val, const T& sum) : val(val), sum(sum) {}
};
const F f;
vector<Node> st[2];
public:
QueueOperateAggregation() = default;
explicit QueueOperateAggregation(F f) : f(f) {}
bool empty() const { return st[0].empty() and st[1].empty(); }
size_t size() const { return st[0].size() + st[1].size(); }
T all_prod() const {
assert(not empty());
if (st[0].empty()) {
return st[1].back().sum;
} else if (st[1].empty()) {
return st[0].back().sum;
} else {
return f(st[0].back().sum, st[1].back().sum);
}
}
void push(const T& x) {
if (st[1].empty()) {
st[1].emplace_back(x, x);
} else {
st[1].emplace_back(x, f(st[1].back().sum, x));
}
}
void pop() {
assert(not empty());
if (st[0].empty()) {
st[0].emplace_back(st[1].back().val, st[1].back().val);
st[1].pop_back();
while (not st[1].empty()) {
st[0].emplace_back(st[1].back().val,
f(st[1].back().val, st[0].back().sum));
st[1].pop_back();
}
}
st[0].pop_back();
}
};
template <typename T, typename F>
QueueOperateAggregation<T, F> get_queue_operate_aggregation(const F& f) {
return QueueOperateAggregation<T, F>{f};
}
#line 1 "structure/others/queue-operate-aggregation.hpp"
template <typename T, typename F>
struct QueueOperateAggregation {
private:
struct Node {
T val, sum;
Node(const T& val, const T& sum) : val(val), sum(sum) {}
};
const F f;
vector<Node> st[2];
public:
QueueOperateAggregation() = default;
explicit QueueOperateAggregation(F f) : f(f) {}
bool empty() const { return st[0].empty() and st[1].empty(); }
size_t size() const { return st[0].size() + st[1].size(); }
T all_prod() const {
assert(not empty());
if (st[0].empty()) {
return st[1].back().sum;
} else if (st[1].empty()) {
return st[0].back().sum;
} else {
return f(st[0].back().sum, st[1].back().sum);
}
}
void push(const T& x) {
if (st[1].empty()) {
st[1].emplace_back(x, x);
} else {
st[1].emplace_back(x, f(st[1].back().sum, x));
}
}
void pop() {
assert(not empty());
if (st[0].empty()) {
st[0].emplace_back(st[1].back().val, st[1].back().val);
st[1].pop_back();
while (not st[1].empty()) {
st[0].emplace_back(st[1].back().val,
f(st[1].back().val, st[0].back().sum));
st[1].pop_back();
}
}
st[0].pop_back();
}
};
template <typename T, typename F>
QueueOperateAggregation<T, F> get_queue_operate_aggregation(const F& f) {
return QueueOperateAggregation<T, F>{f};
}