/
container_utils.hpp
134 lines (125 loc) · 5.76 KB
/
container_utils.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef SUISEN_CONTAINER_UTILS
#define SUISEN_CONTAINER_UTILS
#include <vector>
#include <optional>
#include <sstream>
#include "library/io/input_stream.hpp"
#include "library/io/output_stream.hpp"
#include "library/type_traits/type_traits.hpp"
namespace suisen {
template <typename T>
int count_leq(const std::vector<T> &v, const T &key) { return std::upper_bound(v.begin(), v.end(), key) - v.begin(); }
template <typename T>
int count_lt(const std::vector<T> &v, const T &key) { return std::lower_bound(v.begin(), v.end(), key) - v.begin(); }
template <typename T>
int count_geq(const std::vector<T> &v, const T &key) { return v.size() - count_lt(v, key); }
template <typename T>
int count_gt(const std::vector<T> &v, const T &key) { return v.size() - count_leq(v, key); }
template <typename Container, typename Key>
auto min_geq(const Container &container, const Key &key) -> decltype(std::make_optional(*container.lower_bound(key))) {
if (auto it = container.lower_bound(key); it == container.end()) return std::nullopt;
else return std::make_optional(*it);
}
template <typename Container, typename Key>
auto min_gt(const Container &container, const Key &key) -> decltype(std::make_optional(*container.upper_bound(key))) {
if (auto it = container.upper_bound(key); it == container.end()) return std::nullopt;
else return std::make_optional(*it);
}
template <typename Container, typename Key>
auto max_leq(const Container &container, const Key &key) -> decltype(std::make_optional(*container.upper_bound(key))) {
if (auto it = container.upper_bound(key); it == container.begin()) return std::nullopt;
else return std::make_optional(*--it);
}
template <typename Container, typename Key>
auto max_lt(const Container &container, const Key &key) -> decltype(std::make_optional(*container.lower_bound(key))) {
if (auto it = container.lower_bound(key); it == container.begin()) return std::nullopt;
else return std::make_optional(*--it);
}
template <typename T>
std::optional<T> min_geq(const std::vector<T> &v, const T &key) {
auto it = std::lower_bound(v.begin(), v.end(), key);
return it == v.end() ? std::nullopt : std::make_optional(*it);
}
template <typename T>
std::optional<T> min_gt(const std::vector<T> &v, const T &key) {
auto it = std::upper_bound(v.begin(), v.end(), key);
return it == v.end() ? std::nullopt : std::make_optional(*it);
}
template <typename T>
std::optional<T> max_leq(const std::vector<T> &v, const T &key) {
auto it = std::upper_bound(v.begin(), v.end(), key);
return it == v.begin() ? std::nullopt : std::make_optional(*--it);
}
template <typename T>
std::optional<T> max_lt(const std::vector<T> &v, const T &key) {
auto it = std::lower_bound(v.begin(), v.end(), key);
return it == v.begin() ? std::nullopt : std::make_optional(*--it);
}
__int128_t stoi128(const std::string& s) {
__int128_t res;
io::InputStream{std::istringstream{s}} >> res;
return res;
}
__uint128_t stou128(const std::string& s) {
__uint128_t res;
io::InputStream{std::istringstream{s}} >> res;
return res;
}
template <typename Iterable, std::enable_if_t<suisen::is_iterable_v<Iterable>, std::nullptr_t> = nullptr>
std::string join(const Iterable& v, const std::string& sep, const std::string& end) {
io::OutputStream os{ std::ostringstream{} };
os.print_all(v, sep, end);
return os.get_stream().str();
}
template <typename Iterable, std::enable_if_t<suisen::is_iterable_v<Iterable>, std::nullptr_t> = nullptr>
std::vector<Iterable> split(const Iterable &s, const typename Iterable::value_type &delim) {
std::vector<Iterable> res;
for (auto itl = s.begin(), itr = itl;; itl = ++itr) {
while (itr != s.end() and *itr != delim) ++itr;
res.emplace_back(itl, itr);
if (itr == s.end()) return res;
}
}
template <typename Iterable, std::enable_if_t<suisen::is_iterable_v<Iterable>, std::nullptr_t> = nullptr>
void concat(Iterable& s, const Iterable& t) {
s.reserve(std::size(s) + std::size(t));
std::copy(std::begin(t), std::end(t), std::back_inserter(s));
}
template <typename Iterable, std::enable_if_t<suisen::is_iterable_v<Iterable>, std::nullptr_t> = nullptr>
Iterable concatenated(Iterable s, const Iterable& t) { concat(s, t); return s; }
template <typename Func, typename Iterable, std::enable_if_t<suisen::is_iterable_v<Iterable>, std::nullptr_t> = nullptr>
auto mapped_vec(const Func& f, const Iterable& s) {
std::vector<std::invoke_result_t<Func, typename Iterable::value_type>> v;
v.reserve(std::size(s)), std::transform(s.begin(), s.end(), std::back_inserter(v), f);
return v;
}
template <typename T, typename Iterable, std::enable_if_t<suisen::is_iterable_v<Iterable>, std::nullptr_t> = nullptr>
auto copied_vec(const Iterable& s) {
std::vector<T> v;
v.reserve(std::size(s)), std::copy(s.begin(), s.end(), std::back_inserter(v));
return v;
}
namespace charmap {
int fd(char c) { return c - '0'; }
int fa(char c) { return c - 'a'; }
int fA(char c) { return c - 'A'; }
int faA(char c) { return c <= 'Z' ? c - 'A' : 26 + (c - 'a'); }
}
// val = Sum_i res[i] * base^i
template <int base = 2, typename T, std::enable_if_t<std::is_integral_v<T>, std::nullptr_t> = nullptr>
std::string digits_str(T val, size_t width = 0) {
static_assert(2 <= base and base <= 10);
std::string res;
for (; val or res.size() < width; val /= base) res += '0' + (val % base);
return res;
}
// val = Sum_i res[i] * base^i
template <typename T, typename U = int, std::enable_if_t<std::conjunction_v<std::is_integral<T>, std::is_integral<U>>, std::nullptr_t> = nullptr>
std::vector<U> digits(T val, U base = 10) {
std::vector<U> res;
for (; val; val /= base) res.push_back(val % base);
if (res.empty()) res.push_back(T{ 0 });
return res;
}
} // namespace suisen
#endif // SUISEN_CONTAINER_UTILS