This documentation is automatically generated by online-judge-tools/verification-helper
#include "Src/DataStructure/Heap/BinaryHeap.hpp"要素aに対して、comp(a, b)がtrueになる方が強いという優先度を設けたPriority Queue。std::priority_queueとは逆向きの優先度付けをしているが、こちらの方が直感的に自然だと思う。
template <class T, class Comp = std::less<T>>
requires std::strict_weak_order<Comp, const T&, const T&>
デフォルトでは最小値をtopに持ってくるようになる
BinaryHeap(Comp comp = {}) // (1)
template <std::forward_iterator It>
requires std::same_as<std::iter_value_t<It>, T>
BinaryHeap(It first, It last, Comp comp = {}) // (2)
BinaryHeap(std::vector<T>&& a, Comp comp = {}) // (3)
BinaryHeap(const std::vector<T>& a, Comp comp = {}) // (4)
(1): 空で初期化 $O(1)$
(2), (3), (4): ヒープを構築する。 $O(N)$
inline usize size() const;
inline bool empty() const;
const_iterator begin() const;
const_iterator end() const;
const T& top() const;
void push(T&&);
void push(const T&);
void pop();
std::priority_queueと同じ。begin(), end()が提供されているので、cout << std::vector(que.begin(), que.end()) << endl;みたいなこともできる。
top, popはassertで落ちるようになっている。#pragma once
#include "../../Template/TypeAlias.hpp"
#include <algorithm>
#include <cassert>
#include <concepts>
#include <utility>
#include <vector>
#include <functional>
namespace zawa {
template <class T, class Comp = std::less<T>>
requires std::strict_weak_order<Comp, const T&, const T&>
class BinaryHeap {
private:
Comp m_comp;
std::vector<T> m_dat;
public:
inline usize size() const {
return m_dat.size() - 1;
}
inline bool empty() const {
return m_dat.size() == 1;
}
inline const Comp& comp() const {
return m_comp;
}
using const_iterator = typename decltype(m_dat)::const_iterator;
const_iterator begin() const {
return m_dat.begin() + 1;
}
const_iterator end() const {
return m_dat.end();
}
BinaryHeap(Comp comp = {})
: m_comp{comp}, m_dat(1) {}
template <std::forward_iterator It>
requires std::same_as<std::iter_value_t<It>, T>
BinaryHeap(It first, It last, Comp comp = {})
: m_comp{comp}, m_dat(1) {
m_dat.insert(m_dat.end(), first, last);
build();
}
BinaryHeap(std::vector<T>&& a, Comp comp = {})
: m_comp{comp}, m_dat(a.size() + 1) {
std::ranges::copy(std::make_move_iterator(a.begin()), std::make_move_iterator(a.end()), m_dat.begin() + 1);
build();
}
BinaryHeap(const std::vector<T>& a, Comp comp = {})
: m_comp{comp}, m_dat(a.size() + 1) {
std::ranges::copy(a.begin(), a.end(), m_dat.begin() + 1);
build();
}
const T& top() const {
assert(size() and "HeapUnderFlow");
return m_dat[1];
}
void push(T&& v) {
m_dat.push_back(std::move(v));
upHeap(size());
}
void push(const T& v) {
m_dat.push_back(v);
upHeap(size());
}
void pop() {
assert(size() and "HeapUnderFlow");
if (size() > 1)
std::swap(m_dat[1], m_dat.back());
m_dat.pop_back();
if (size() > 1)
downHeap(1, size());
}
private:
void build() {
const usize n = size();
for (usize i = (n >> 1) ; i ; i--)
downHeap(i, n);
}
void upHeap(usize i) {
while (i >> 1 and m_comp(m_dat[i], m_dat[i >> 1])) {
std::swap(m_dat[i], m_dat[i >> 1]);
i >>= 1;
}
}
void downHeap(usize i, usize n) {
while ((i << 1) <= n) {
usize j = i << 1;
if (j + 1 <= n and m_comp(m_dat[j + 1], m_dat[j]))
j++;
if (!m_comp(m_dat[j], m_dat[i]))
break;
std::swap(m_dat[i], m_dat[j]);
i = j;
}
}
};
} // namespace zawa#line 2 "Src/DataStructure/Heap/BinaryHeap.hpp"
#line 2 "Src/Template/TypeAlias.hpp"
#include <cstdint>
#include <cstddef>
namespace zawa {
using i16 = std::int16_t;
using i32 = std::int32_t;
using i64 = std::int64_t;
using i128 = __int128_t;
using u8 = std::uint8_t;
using u16 = std::uint16_t;
using u32 = std::uint32_t;
using u64 = std::uint64_t;
using usize = std::size_t;
} // namespace zawa
#line 4 "Src/DataStructure/Heap/BinaryHeap.hpp"
#include <algorithm>
#include <cassert>
#include <concepts>
#include <utility>
#include <vector>
#include <functional>
namespace zawa {
template <class T, class Comp = std::less<T>>
requires std::strict_weak_order<Comp, const T&, const T&>
class BinaryHeap {
private:
Comp m_comp;
std::vector<T> m_dat;
public:
inline usize size() const {
return m_dat.size() - 1;
}
inline bool empty() const {
return m_dat.size() == 1;
}
inline const Comp& comp() const {
return m_comp;
}
using const_iterator = typename decltype(m_dat)::const_iterator;
const_iterator begin() const {
return m_dat.begin() + 1;
}
const_iterator end() const {
return m_dat.end();
}
BinaryHeap(Comp comp = {})
: m_comp{comp}, m_dat(1) {}
template <std::forward_iterator It>
requires std::same_as<std::iter_value_t<It>, T>
BinaryHeap(It first, It last, Comp comp = {})
: m_comp{comp}, m_dat(1) {
m_dat.insert(m_dat.end(), first, last);
build();
}
BinaryHeap(std::vector<T>&& a, Comp comp = {})
: m_comp{comp}, m_dat(a.size() + 1) {
std::ranges::copy(std::make_move_iterator(a.begin()), std::make_move_iterator(a.end()), m_dat.begin() + 1);
build();
}
BinaryHeap(const std::vector<T>& a, Comp comp = {})
: m_comp{comp}, m_dat(a.size() + 1) {
std::ranges::copy(a.begin(), a.end(), m_dat.begin() + 1);
build();
}
const T& top() const {
assert(size() and "HeapUnderFlow");
return m_dat[1];
}
void push(T&& v) {
m_dat.push_back(std::move(v));
upHeap(size());
}
void push(const T& v) {
m_dat.push_back(v);
upHeap(size());
}
void pop() {
assert(size() and "HeapUnderFlow");
if (size() > 1)
std::swap(m_dat[1], m_dat.back());
m_dat.pop_back();
if (size() > 1)
downHeap(1, size());
}
private:
void build() {
const usize n = size();
for (usize i = (n >> 1) ; i ; i--)
downHeap(i, n);
}
void upHeap(usize i) {
while (i >> 1 and m_comp(m_dat[i], m_dat[i >> 1])) {
std::swap(m_dat[i], m_dat[i >> 1]);
i >>= 1;
}
}
void downHeap(usize i, usize n) {
while ((i << 1) <= n) {
usize j = i << 1;
if (j + 1 <= n and m_comp(m_dat[j + 1], m_dat[j]))
j++;
if (!m_comp(m_dat[j], m_dat[i]))
break;
std::swap(m_dat[i], m_dat[j]);
i = j;
}
}
};
} // namespace zawa