From 60fc2a123c90e021c5668840b1580121f6689116 Mon Sep 17 00:00:00 2001 From: Barrett Ruth Date: Fri, 28 Feb 2025 11:35:58 -0500 Subject: [PATCH] feat(cses): range queries ; --- codeforces/974/h.in | 16 +- codeforces/974/h.out | 9 +- cses/range-queries/.clang-format | 9 + cses/range-queries/.clangd | 8 + cses/range-queries/compile_flags.txt | 6 + .../dynamic-range-minimum-queries.cc | 176 +++++++++++ .../dynamic-range-minimum-queries.in | 6 + .../dynamic-range-minimum-queries.out | 6 + .../dynamic-range-sum-queries.cc | 164 +++++++++++ .../dynamic-range-sum-queries.in | 6 + .../dynamic-range-sum-queries.out | 6 + cses/range-queries/forest-queries.cc | 93 ++++++ cses/range-queries/forest-queries.in | 8 + cses/range-queries/forest-queries.out | 6 + cses/range-queries/hotel-queries.cc | 209 +++++++++++++ cses/range-queries/hotel-queries.in | 3 + cses/range-queries/hotel-queries.out | 3 + cses/range-queries/list-removals.cc | 276 ++++++++++++++++++ cses/range-queries/list-removals.in | 3 + cses/range-queries/list-removals.out | 3 + cses/range-queries/range-update-queries.cc | 173 +++++++++++ cses/range-queries/range-update-queries.in | 5 + cses/range-queries/range-update-queries.out | 5 + cses/range-queries/range-xor-queries.cc | 79 +++++ cses/range-queries/range-xor-queries.in | 6 + cses/range-queries/range-xor-queries.out | 7 + cses/range-queries/rui | 55 ++++ cses/range-queries/salary-queries-fenwick.cc | 183 ++++++++++++ cses/range-queries/salary-queries-fenwick.in | 12 + cses/range-queries/salary-queries-fenwick.out | 12 + cses/range-queries/salary-queries-pbds.cc | 197 +++++++++++++ cses/range-queries/salary-queries-pbds.in | 12 + cses/range-queries/salary-queries-pbds.out | 10 + .../static-range-minimum-queries.cc | 111 +++++++ .../static-range-minimum-queries.in | 6 + .../static-range-minimum-queries.out | 7 + .../range-queries/static-sum-range-queries.cc | 154 ++++++++++ .../range-queries/static-sum-range-queries.in | 6 + .../static-sum-range-queries.out | 7 + 39 files changed, 2044 insertions(+), 19 deletions(-) create mode 100644 cses/range-queries/.clang-format create mode 100644 cses/range-queries/.clangd create mode 100644 cses/range-queries/compile_flags.txt create mode 100644 cses/range-queries/dynamic-range-minimum-queries.cc create mode 100644 cses/range-queries/dynamic-range-minimum-queries.in create mode 100644 cses/range-queries/dynamic-range-minimum-queries.out create mode 100644 cses/range-queries/dynamic-range-sum-queries.cc create mode 100644 cses/range-queries/dynamic-range-sum-queries.in create mode 100644 cses/range-queries/dynamic-range-sum-queries.out create mode 100644 cses/range-queries/forest-queries.cc create mode 100644 cses/range-queries/forest-queries.in create mode 100644 cses/range-queries/forest-queries.out create mode 100644 cses/range-queries/hotel-queries.cc create mode 100644 cses/range-queries/hotel-queries.in create mode 100644 cses/range-queries/hotel-queries.out create mode 100644 cses/range-queries/list-removals.cc create mode 100644 cses/range-queries/list-removals.in create mode 100644 cses/range-queries/list-removals.out create mode 100644 cses/range-queries/range-update-queries.cc create mode 100644 cses/range-queries/range-update-queries.in create mode 100644 cses/range-queries/range-update-queries.out create mode 100644 cses/range-queries/range-xor-queries.cc create mode 100644 cses/range-queries/range-xor-queries.in create mode 100644 cses/range-queries/range-xor-queries.out create mode 100644 cses/range-queries/rui create mode 100644 cses/range-queries/salary-queries-fenwick.cc create mode 100644 cses/range-queries/salary-queries-fenwick.in create mode 100644 cses/range-queries/salary-queries-fenwick.out create mode 100644 cses/range-queries/salary-queries-pbds.cc create mode 100644 cses/range-queries/salary-queries-pbds.in create mode 100644 cses/range-queries/salary-queries-pbds.out create mode 100644 cses/range-queries/static-range-minimum-queries.cc create mode 100644 cses/range-queries/static-range-minimum-queries.in create mode 100644 cses/range-queries/static-range-minimum-queries.out create mode 100644 cses/range-queries/static-sum-range-queries.cc create mode 100644 cses/range-queries/static-sum-range-queries.in create mode 100644 cses/range-queries/static-sum-range-queries.out diff --git a/codeforces/974/h.in b/codeforces/974/h.in index 50a09d9..fdc6ba8 100644 --- a/codeforces/974/h.in +++ b/codeforces/974/h.in @@ -1,12 +1,4 @@ -2 -3 3 -1 2 2 -1 2 -1 3 -2 3 -5 3 -2 1 2 1 1 -1 2 -1 3 -4 5 - +1 +5 1 +1 2 3 4 5 6 7 +1 7 diff --git a/codeforces/974/h.out b/codeforces/974/h.out index 4d18bd6..9b3f3b5 100644 --- a/codeforces/974/h.out +++ b/codeforces/974/h.out @@ -1,9 +1,4 @@ -no -no -yes -no -no -yes +NO [code]: 0 -[time]: 11.7841 ms \ No newline at end of file +[time]: 11.6379 ms \ No newline at end of file diff --git a/cses/range-queries/.clang-format b/cses/range-queries/.clang-format new file mode 100644 index 0000000..e7350c4 --- /dev/null +++ b/cses/range-queries/.clang-format @@ -0,0 +1,9 @@ +BasedOnStyle: Google +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: false +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: false +AllowShortIfStatementsOnASingleLine: false +AllowShortLambdasOnASingleLine: false +AllowShortLoopsOnASingleLine: false diff --git a/cses/range-queries/.clangd b/cses/range-queries/.clangd new file mode 100644 index 0000000..4f8ead9 --- /dev/null +++ b/cses/range-queries/.clangd @@ -0,0 +1,8 @@ +CompileFlags: + Add: + - -Wall + - -Wextra + - -Wpedantic + - -Wshadow + - -DLOCAL + - -Wno-unknown-pragmas \ No newline at end of file diff --git a/cses/range-queries/compile_flags.txt b/cses/range-queries/compile_flags.txt new file mode 100644 index 0000000..573a6b6 --- /dev/null +++ b/cses/range-queries/compile_flags.txt @@ -0,0 +1,6 @@ +-Wall +-Wextra +-Wpedantic +-Wshadow +-DLOCAL +-std=c++20 diff --git a/cses/range-queries/dynamic-range-minimum-queries.cc b/cses/range-queries/dynamic-range-minimum-queries.cc new file mode 100644 index 0000000..eedb5b9 --- /dev/null +++ b/cses/range-queries/dynamic-range-minimum-queries.cc @@ -0,0 +1,176 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct segment_tree { + public: + explicit segment_tree(std::vector const& ts) : n(ts.size()) { + tree.resize(4 * n); + build(1, 0, n - 1, ts); + } + + [[nodiscard]] T const query(int const l, int const r) const { + if (!(0 <= l && l <= r && r < static_cast(n))) { + throw std::out_of_range( + "cannot query segment tree of size " + std::to_string(n) + + " at range [" + std::to_string(l) + ", " + std::to_string(r) + "]"); + } + + return query(1, 0, n - 1, l, r); + } + + void update(int i, T const& t) { + if (!(0 <= i && i < static_cast(n))) { + throw std::out_of_range("cannot update segment tree of size " + + std::to_string(n) + " at index " + + std::to_string(i)); + } + + update(1, 0, n - 1, i, t); + } + + private: + inline T const sentinel() const noexcept { + return MAX; + } + + inline T const merge(T const& x, T const& y) const noexcept { + return min(x, y); + } + + void build(size_t const node, size_t const l, size_t const r, + std::vector const& ts) noexcept { + if (l == r) { + tree[node] = ts[l]; + } else { + int m = l + (r - l) / 2; + build(2 * node, l, m, ts); + build(2 * node + 1, m + 1, r, ts); + tree[node] = merge(tree[2 * node], tree[2 * node + 1]); + } + } + + [[nodiscard]] T query(size_t const node, size_t const lower, + size_t const upper, size_t const l, + size_t const r) const noexcept { + if (upper < l || r < lower) { + return sentinel(); + } + + if (l <= lower && upper <= r) { + return tree[node]; + } + + size_t m = lower + (upper - lower) / 2; + + return merge(query(2 * node, lower, m, l, r), + query(2 * node + 1, m + 1, upper, l, r)); + } + + void update(size_t const node, size_t const l, size_t const r, size_t const i, + T const& t) noexcept { + if (l == r) { + tree[node] = t; + } else { + size_t m = l + (r - l) / 2; + if (i <= m) { + update(2 * node, l, m, i, t); + } else { + update(2 * node + 1, m + 1, r, i, t); + } + tree[node] = merge(tree[2 * node], tree[2 * node + 1]); + } + } + + size_t n; + std::vector tree; +}; + +void solve() { + int n, q; + cin >> n >> q; + v a(n); + for (auto& e : a) { + cin >> e; + } + segment_tree st(a); + + while (q--) { + char cmd; + cin >> cmd; + if (cmd == '1') { + int i; + ll u; + cin >> i >> u; + --i; + st.update(i, u); + a[i] = u; + } else { + int l, r; + cin >> l >> r; + --l; + --r; + cout << st.query(l, r) << endl; + } + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/dynamic-range-minimum-queries.in b/cses/range-queries/dynamic-range-minimum-queries.in new file mode 100644 index 0000000..1f69ad7 --- /dev/null +++ b/cses/range-queries/dynamic-range-minimum-queries.in @@ -0,0 +1,6 @@ +8 4 +3 2 4 5 1 1 5 3 +2 1 4 +2 5 6 +1 2 3 +2 1 4 diff --git a/cses/range-queries/dynamic-range-minimum-queries.out b/cses/range-queries/dynamic-range-minimum-queries.out new file mode 100644 index 0000000..91bce2d --- /dev/null +++ b/cses/range-queries/dynamic-range-minimum-queries.out @@ -0,0 +1,6 @@ +2 +1 +3 + +[code]: 0 +[time]: 13.1326 ms \ No newline at end of file diff --git a/cses/range-queries/dynamic-range-sum-queries.cc b/cses/range-queries/dynamic-range-sum-queries.cc new file mode 100644 index 0000000..65223a5 --- /dev/null +++ b/cses/range-queries/dynamic-range-sum-queries.cc @@ -0,0 +1,164 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct fenwick_tree { + public: + explicit fenwick_tree(std::vector const& ts) : tree(ts.size()) { + for (size_t i = 0; i < ts.size(); ++i) { + tree[i] = ts[i]; + } + for (size_t i = 0; i < tree.size(); ++i) { + size_t j = g(i); + if (j < tree.size()) { + tree[j] += tree[i]; + } + } + } + + T const query(int i) const { + if (!(0 <= i && i < static_cast(tree.size()))) { + return T(); + } + + T t = sentinel(); + + for (int j = static_cast(i); j >= 0; j = h(j) - 1) { + t = merge(t, tree[j]); + } + + return t; + }; + + T const query(int l, int r) const { + if (!(0 <= l && r < static_cast(tree.size()))) { + return T(); + } + + if (l == 0) { + return query(r); + } + + return unmerge(query(r), query(l - 1)); + }; + + void update(int i, T const& t) noexcept { + assert(0 <= i && i < static_cast(tree.size())); + + for (size_t j = i; j < tree.size(); j = g(j)) { + tree[j] = merge(tree[j], t); + } + } + + private: + [[nodiscard]] inline T merge(T const& x, T const& y) const noexcept { + return x + y; + } + + [[nodiscard]] inline T unmerge(T const& x, T const& y) const noexcept { + return x - y; + } + + [[nodiscard]] inline T sentinel() const noexcept { + return 0; + } + + [[nodiscard]] inline size_t g(size_t i) const noexcept { + return i | (i + 1); + } + + [[nodiscard]] inline size_t h(size_t i) const noexcept { + return i & (i + 1); + } + + std::vector tree; +}; + +void solve() { + int n, q; + cin >> n >> q; + + v a(n); + for (auto& e : a) + cin >> e; + + fenwick_tree fw(a); + while (q--) { + char cmd; + cin >> cmd; + if (cmd == '1') { + int i; + ll u; + cin >> i >> u; + --i; + fw.update(i, u - a[i]); + a[i] = u; + } else { + int l, r; + cin >> l >> r; + --l; + --r; + cout << fw.query(l, r) << endl; + } + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/dynamic-range-sum-queries.in b/cses/range-queries/dynamic-range-sum-queries.in new file mode 100644 index 0000000..9b1355e --- /dev/null +++ b/cses/range-queries/dynamic-range-sum-queries.in @@ -0,0 +1,6 @@ +8 4 +3 2 4 5 1 1 5 3 +2 1 4 +2 5 6 +1 3 1 +2 1 4 diff --git a/cses/range-queries/dynamic-range-sum-queries.out b/cses/range-queries/dynamic-range-sum-queries.out new file mode 100644 index 0000000..91b9f94 --- /dev/null +++ b/cses/range-queries/dynamic-range-sum-queries.out @@ -0,0 +1,6 @@ +14 +2 +11 + +[code]: 0 +[time]: 14.9324 ms \ No newline at end of file diff --git a/cses/range-queries/forest-queries.cc b/cses/range-queries/forest-queries.cc new file mode 100644 index 0000000..bee778b --- /dev/null +++ b/cses/range-queries/forest-queries.cc @@ -0,0 +1,93 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +void solve() { + int n, q; + cin >> n >> q; + v grid(n); + for (int i = 0; i < n; ++i) { + cin >> grid[i]; + } + + v> prefix(n + 1, v(n + 1, 0)); + + for (int i = 0; i < n; ++i) { + prefix[1][i + 1] = prefix[1][i] + (grid[0][i] == '*'); + } + + for (int i = 1; i < n; ++i) { + prefix[i + 1][1] = prefix[i][1] + (grid[i][0] == '*'); + for (int j = 1; j < n; ++j) { + prefix[i + 1][j + 1] = prefix[i + 1][j] + prefix[i][j + 1] - + prefix[i][j] + (grid[i][j] == '*'); + } + } + + while (q--) { + int y1, x1, y2, x2; + cin >> y1 >> x1 >> y2 >> x2; + cout << prefix[y2][x2] - prefix[y2][x1 - 1] - prefix[y1 - 1][x2] + + prefix[y1 - 1][x1 - 1] + << endl; + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/forest-queries.in b/cses/range-queries/forest-queries.in new file mode 100644 index 0000000..38755aa --- /dev/null +++ b/cses/range-queries/forest-queries.in @@ -0,0 +1,8 @@ +4 3 +.*.. +*.** +**.. +**** +2 2 3 4 +3 1 3 1 +1 1 2 2 diff --git a/cses/range-queries/forest-queries.out b/cses/range-queries/forest-queries.out new file mode 100644 index 0000000..a913b5c --- /dev/null +++ b/cses/range-queries/forest-queries.out @@ -0,0 +1,6 @@ +3 +1 +2 + +[code]: 0 +[time]: 13.4509 ms \ No newline at end of file diff --git a/cses/range-queries/hotel-queries.cc b/cses/range-queries/hotel-queries.cc new file mode 100644 index 0000000..9354597 --- /dev/null +++ b/cses/range-queries/hotel-queries.cc @@ -0,0 +1,209 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct segment_tree { + public: + explicit segment_tree(std::vector const& ts) : n(ts.size()) { + tree.resize(4 * n); + build(1, 0, n - 1, ts); + } + + [[nodiscard]] T const query(int const l, int const r) const { + if (!(0 <= l && l <= r && r < static_cast(n))) { + throw std::out_of_range( + "cannot query segment tree of size " + std::to_string(n) + + " at range [" + std::to_string(l) + ", " + std::to_string(r) + "]"); + } + + return query(1, 0, n - 1, l, r); + } + + void update(int i, T const& t) { + if (!(0 <= i && i < static_cast(n))) { + throw std::out_of_range("cannot update segment tree of size " + + std::to_string(n) + " at index " + + std::to_string(i)); + } + + update(1, 0, n - 1, i, t); + } + + [[nodiscard]] size_t lower_bound(T const& t) const noexcept { + return lower_bound(1, 0, n - 1, t); + } + + [[nodiscard]] size_t upper_bound(T const& t) const noexcept { + return upper_bound(1, 0, n - 1, t); + } + + private: + inline T const sentinel() const noexcept { + return MIN; + } + + inline T const merge(T const& x, T const& y) const noexcept { + return max(x, y); + } + + void build(size_t const node, size_t const l, size_t const r, + std::vector const& ts) noexcept { + if (l == r) { + tree[node] = ts[l]; + } else { + int m = l + (r - l) / 2; + build(2 * node, l, m, ts); + build(2 * node + 1, m + 1, r, ts); + tree[node] = merge(tree[2 * node], tree[2 * node + 1]); + } + } + + [[nodiscard]] T query(size_t const node, size_t const lower, + size_t const upper, size_t const l, + size_t const r) const noexcept { + if (upper < l || r < lower) { + return sentinel(); + } + + if (l <= lower && upper <= r) { + return tree[node]; + } + + size_t m = lower + (upper - lower) / 2; + + return merge(query(2 * node, lower, m, l, r), + query(2 * node + 1, m + 1, upper, l, r)); + } + + void update(size_t const node, size_t const l, size_t const r, size_t const i, + T const& t) noexcept { + if (l == r) { + tree[node] = t; + } else { + size_t m = l + (r - l) / 2; + if (i <= m) { + update(2 * node, l, m, i, t); + } else { + update(2 * node + 1, m + 1, r, i, t); + } + tree[node] = merge(tree[2 * node], tree[2 * node + 1]); + } + } + + [[nodiscard]] size_t lower_bound(size_t const node, size_t const l, + size_t const r, T const& t) const noexcept { + if (l == r) { + return tree[node] >= t ? l : n; + } + + size_t m = l + (r - l) / 2; + if (tree[2 * node] >= t) { + size_t res = lower_bound(2 * node, l, m, t); + if (res < n) + return res; + } + + return lower_bound(2 * node + 1, m + 1, r, t); + } + + [[nodiscard]] size_t upper_bound(size_t const node, size_t const l, + size_t const r, T const& t) const noexcept { + if (l == r) { + return tree[node] > t ? l : n; + } + + size_t m = l + (r - l) / 2; + if (tree[2 * node] > t) { + size_t res = upper_bound(2 * node, l, m, t); + if (res < n) + return res; + } + + return upper_bound(2 * node + 1, m + 1, r, t); + } + + size_t n; + std::vector tree; +}; + +void solve() { + int n, m; + cin >> n >> m; + v a(n); + for (auto& e : a) + cin >> e; + segment_tree st(a); + + while (m--) { + ll x; + cin >> x; + int i = st.lower_bound(x); + if (i == n) { + cout << 0 << ' '; + } else { + cout << i + 1 << ' '; + st.update(i, a[i] - x); + a[i] -= x; + } + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/hotel-queries.in b/cses/range-queries/hotel-queries.in new file mode 100644 index 0000000..2c0a15f --- /dev/null +++ b/cses/range-queries/hotel-queries.in @@ -0,0 +1,3 @@ +8 5 +3 2 4 1 5 5 2 6 +4 4 7 1 1 diff --git a/cses/range-queries/hotel-queries.out b/cses/range-queries/hotel-queries.out new file mode 100644 index 0000000..3546bbc --- /dev/null +++ b/cses/range-queries/hotel-queries.out @@ -0,0 +1,3 @@ +3 5 0 1 1 +[code]: 0 +[time]: 14.4272 ms \ No newline at end of file diff --git a/cses/range-queries/list-removals.cc b/cses/range-queries/list-removals.cc new file mode 100644 index 0000000..560b712 --- /dev/null +++ b/cses/range-queries/list-removals.cc @@ -0,0 +1,276 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +[[nodiscard]] static T MIN() { + return std::numeric_limits::min(); +} + +template +[[nodiscard]] static T MAX() { + return std::numeric_limits::max(); +} + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct fenwick_tree { + public: + explicit fenwick_tree(size_t n) : tree(n, 1) { + for (size_t i = 0; i < tree.size(); ++i) { + size_t j = g(i); + if (j < tree.size()) { + tree[j] += tree[i]; + } + } + } + + T const query(int i) const { + if (!(0 <= i && i < static_cast(tree.size()))) { + throw std::out_of_range("cannot query fenwick tree of size " + + std::to_string(tree.size()) + " at index " + + std::to_string(i)); + } + + T t = sentinel(); + + for (int j = static_cast(i); j >= 0; j = h(j) - 1) { + t = merge(t, tree[j]); + } + + return t; + }; + + T const query(int l, int r) const { + if (!(0 <= l && l <= r && r < static_cast(tree.size()))) { + throw std::out_of_range( + "cannot query fenwick tree of size " + std::to_string(tree.size()) + + " at range [" + std::to_string(l) + ", " + std::to_string(r) + "]"); + } + + if (l == 0) { + return query(r); + } + + return unmerge(query(r), query(l - 1)); + }; + + void update(int i, T const& t) noexcept { + assert(0 <= i && i < static_cast(tree.size())); + + for (size_t j = i; j < tree.size(); j = g(j)) { + tree[j] = merge(tree[j], t); + } + } + + private: + [[nodiscard]] inline T merge(T const& x, T const& y) const noexcept { + return x + y; + } + + [[nodiscard]] inline T unmerge(T const& x, T const& y) const noexcept { + return x - y; + } + + [[nodiscard]] inline T sentinel() const noexcept { + return 0; + } + + [[nodiscard]] inline size_t g(size_t i) const noexcept { + return i | (i + 1); + } + + [[nodiscard]] inline size_t h(size_t i) const noexcept { + return i & (i + 1); + } + + std::vector tree; +}; + +#include +#include + +using namespace __gnu_pbds; + +// https://mirror.codeforces.com/blog/entry/124683 + +namespace hashing { +using i64 = std::int64_t; +using u64 = std::uint64_t; +static const u64 FIXED_RANDOM = + std::chrono::steady_clock::now().time_since_epoch().count(); + +#if USE_AES +std::mt19937 rd(FIXED_RANDOM); +const __m128i KEY1{(i64)rd(), (i64)rd()}; +const __m128i KEY2{(i64)rd(), (i64)rd()}; +#endif + +template +struct custom_hash {}; + +template +inline void hash_combine(u64& seed, T const& v) { + custom_hash hasher; + seed ^= hasher(v) + 0x9e3779b97f4a7c15 + (seed << 12) + (seed >> 4); +}; + +template +struct custom_hash::value>::type> { + u64 operator()(T _x) const { + u64 x = _x; +#if USE_AES + __m128i m{i64(u64(x) * 0xbf58476d1ce4e5b9u64), (i64)FIXED_RANDOM}; + __m128i y = _mm_aesenc_si128(m, KEY1); + __m128i z = _mm_aesenc_si128(y, KEY2); + return z[0]; +#else + x += 0x9e3779b97f4a7c15 + FIXED_RANDOM; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; + x = (x ^ (x >> 27)) * 0x94d049bb133111eb; + return x ^ (x >> 31); +#endif + } +}; + +template +struct custom_hash()))>> { + u64 operator()(T const& a) const { + u64 value = FIXED_RANDOM; + for (auto& x : a) + hash_combine(value, x); + return value; + } +}; + +template +struct custom_hash> { + u64 operator()(const std::tuple& a) const { + u64 value = FIXED_RANDOM; + std::apply( + [&value](T const&... args) { + (hash_combine(value, args), ...); + }, + a); + return value; + } +}; + +template +struct custom_hash> { + u64 operator()(std::pair const& a) const { + u64 value = FIXED_RANDOM; + hash_combine(value, a.first); + hash_combine(value, a.second); + return value; + } +}; +}; // namespace hashing + +#ifdef PB_DS_ASSOC_CNTNR_HPP +template +using hashtable = gp_hash_table< + Key, Value, hashing::custom_hash, std::equal_to, + direct_mask_range_hashing<>, linear_probe_fn<>, + hash_standard_resize_policy, + hash_load_check_resize_trigger<>, true>>; + +#endif +#ifdef PB_DS_TREE_POLICY_HPP +template +using multitree = tree, rb_tree_tag, + tree_order_statistics_node_update>; +template +using rbtree = tree, rb_tree_tag, + tree_order_statistics_node_update>; +#endif + +void solve() { + int n; + cin >> n; + v a(n); + rbtree t; + for (int i = 0; i < n; ++i) { + cin >> a[i]; + t.insert(i); + } + + // fenwick_tree fw(n); + + int p; + for (int i = 0; i < n; ++i) { + cin >> p; + --p; + + int ans = *t.find_by_order(p); + t.erase(ans); + cout << a[ans] << ' '; + + // int l = 0, r = n - 1; + // while (l <= r) { + // int m = l + (r - l) / 2; + // int q = fw.query(m); + // if (q >= p) { + // r = m - 1; + // } else if (q < p) { + // l = m + 1; + // } + // } + // cout << a[l] << ' '; + // + // fw.update(l, -1); + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/list-removals.in b/cses/range-queries/list-removals.in new file mode 100644 index 0000000..ad34528 --- /dev/null +++ b/cses/range-queries/list-removals.in @@ -0,0 +1,3 @@ +5 +2 6 1 4 2 +3 1 3 1 1 diff --git a/cses/range-queries/list-removals.out b/cses/range-queries/list-removals.out new file mode 100644 index 0000000..73e2cce --- /dev/null +++ b/cses/range-queries/list-removals.out @@ -0,0 +1,3 @@ +1 2 2 6 4 +[code]: 0 +[time]: 5.29647 ms \ No newline at end of file diff --git a/cses/range-queries/range-update-queries.cc b/cses/range-queries/range-update-queries.cc new file mode 100644 index 0000000..3c6b1ef --- /dev/null +++ b/cses/range-queries/range-update-queries.cc @@ -0,0 +1,173 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct fenwick_tree { + public: + explicit fenwick_tree(std::vector const& ts) : tree(ts.size()) { + for (size_t i = 0; i < ts.size(); ++i) { + tree[i] = ts[i]; + } + for (size_t i = 0; i < tree.size(); ++i) { + size_t j = g(i); + if (j < tree.size()) { + tree[j] += tree[i]; + } + } + } + + fenwick_tree(size_t n) : tree(n, 0) { + } + + T const query(int i) const { + if (!(0 <= i && i < static_cast(tree.size()))) { + throw std::out_of_range("cannot query fenwick tree of size " + + std::to_string(tree.size()) + " at index " + + std::to_string(i)); + } + + T t = sentinel(); + + for (int j = static_cast(i); j >= 0; j = h(j) - 1) { + t = merge(t, tree[j]); + } + + return t; + }; + + T const query(int l, int r) const { + if (!(0 <= l && l <= r && r < static_cast(tree.size()))) { + throw std::out_of_range( + "cannot query fenwick tree of size " + std::to_string(tree.size()) + + " at range [" + std::to_string(l) + ", " + std::to_string(r) + "]"); + } + + if (l == 0) { + return query(r); + } + + return unmerge(query(r), query(l - 1)); + }; + + void update(int i, T const& t) noexcept { + if (!(0 <= i && i < static_cast(tree.size()))) + return; + + for (size_t j = i; j < tree.size(); j = g(j)) { + tree[j] = merge(tree[j], t); + } + } + + private: + [[nodiscard]] inline T merge(T const& x, T const& y) const noexcept { + return x + y; + } + + [[nodiscard]] inline T unmerge(T const& x, T const& y) const noexcept { + return x - y; + } + + [[nodiscard]] inline T sentinel() const noexcept { + return 0; + } + + [[nodiscard]] inline size_t g(size_t i) const noexcept { + return i | (i + 1); + } + + [[nodiscard]] inline size_t h(size_t i) const noexcept { + return i & (i + 1); + } + + std::vector tree; +}; + +void solve() { + int n, q; + cin >> n >> q; + v a(n); + for (auto& e : a) { + cin >> e; + } + + fenwick_tree fw(n); + + while (q--) { + char cmd; + cin >> cmd; + if (cmd == '1') { + int l, r; + ll u; + cin >> l >> r >> u; + --l; + --r; + fw.update(l, u); + fw.update(r + 1, -u); + } else { + ll i; + cin >> i; + --i; + cout << a[i] + fw.query(i) << endl; + } + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/range-update-queries.in b/cses/range-queries/range-update-queries.in new file mode 100644 index 0000000..6d58ff5 --- /dev/null +++ b/cses/range-queries/range-update-queries.in @@ -0,0 +1,5 @@ +8 3 +3 2 4 5 1 1 5 3 +2 4 +1 2 5 1 +2 4 diff --git a/cses/range-queries/range-update-queries.out b/cses/range-queries/range-update-queries.out new file mode 100644 index 0000000..2a42791 --- /dev/null +++ b/cses/range-queries/range-update-queries.out @@ -0,0 +1,5 @@ +5 +6 + +[code]: 0 +[time]: 12.8767 ms \ No newline at end of file diff --git a/cses/range-queries/range-xor-queries.cc b/cses/range-queries/range-xor-queries.cc new file mode 100644 index 0000000..f2fba58 --- /dev/null +++ b/cses/range-queries/range-xor-queries.cc @@ -0,0 +1,79 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +void solve() { + int n, q; + cin >> n >> q; + v a(n); + v prefix(n + 1, 0); + for (int i = 0; i < n; ++i) { + cin >> a[i]; + prefix[i + 1] = prefix[i] ^ a[i]; + } + + while (q--) { + ll l, r; + cin >> l >> r; + cout << (prefix[r] ^ prefix[l - 1]) << endl; + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/range-xor-queries.in b/cses/range-queries/range-xor-queries.in new file mode 100644 index 0000000..98badeb --- /dev/null +++ b/cses/range-queries/range-xor-queries.in @@ -0,0 +1,6 @@ +8 4 +3 2 4 5 1 1 5 3 +2 4 +5 6 +1 8 +3 3 diff --git a/cses/range-queries/range-xor-queries.out b/cses/range-queries/range-xor-queries.out new file mode 100644 index 0000000..3485424 --- /dev/null +++ b/cses/range-queries/range-xor-queries.out @@ -0,0 +1,7 @@ +3 +0 +6 +4 + +[code]: 0 +[time]: 14.6589 ms \ No newline at end of file diff --git a/cses/range-queries/rui b/cses/range-queries/rui new file mode 100644 index 0000000..f0c957b --- /dev/null +++ b/cses/range-queries/rui @@ -0,0 +1,55 @@ + + +basically allows for answering queries of a range [l, r] + +and updating values/ranges in O(lg(n)) + + +so, for example, finding the minimum of elements in range [l, r] +can be answered in log(n) rather than r - l + 1 + + +basically, you divide up the array into pieces: + + +this is the segtree +for each "segment" you store the answer for the query +[--------------- + x] +[------ + x][-------] +[--][-- + x][--][---] +[-][-][x][-][-][-] + +usually way too advanced + +its super powerful b/c you can, for example +find min/max/sum/gcd over ranges, while updating those values OR + +updating a [l, r] range of values, all in O(lgn) + +so, for example: + +- sum from l to r +- update at index i +- increase indices [l, r] by x + +^ all in log(n) +(pretty insane) + +yes, but i alr knew it before + +adv algos is tuff + +say i update something to x +then i need to go back UP and update each segment + +so it takes: O(lg(n)) time too + +the problem: intervals don't cleanly overlap + +so if i do sum[0:n/2+2] + +i first get sum[0:n/2], then combine with sum[n/2:n/2+2] +the "height" is O(log(n)), so in worst-case you traverse down +the entire depth to combine the sum + +last thing: updating a value diff --git a/cses/range-queries/salary-queries-fenwick.cc b/cses/range-queries/salary-queries-fenwick.cc new file mode 100644 index 0000000..f0ac71e --- /dev/null +++ b/cses/range-queries/salary-queries-fenwick.cc @@ -0,0 +1,183 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +[[nodiscard]] static T MIN() { + return std::numeric_limits::min(); +} + +template +[[nodiscard]] static T MAX() { + return std::numeric_limits::max(); +} + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct fenwick_tree { + public: + explicit fenwick_tree(size_t n) : tree(n) { + } + + T const query(int i) const { + if (!(0 <= i && i < static_cast(tree.size()))) { + throw std::out_of_range("cannot query fenwick tree of size " + + std::to_string(tree.size()) + " at index " + + std::to_string(i)); + } + + T t = sentinel(); + + for (int j = static_cast(i); j >= 0; j = h(j) - 1) { + t = merge(t, tree[j]); + } + + return t; + }; + + T const query(int l, int r) const { + if (!(0 <= l && l <= r && r < static_cast(tree.size()))) { + throw std::out_of_range( + "cannot query fenwick tree of size " + std::to_string(tree.size()) + + " at range [" + std::to_string(l) + ", " + std::to_string(r) + "]"); + } + + if (l == 0) { + return query(r); + } + + return unmerge(query(r), query(l - 1)); + }; + + void update(int i, T const& t) noexcept { + assert(0 <= i && i < static_cast(tree.size())); + + for (size_t j = i; j < tree.size(); j = g(j)) { + tree[j] = merge(tree[j], t); + } + } + + private: + [[nodiscard]] inline T merge(T const& x, T const& y) const noexcept { + return x + y; + } + + [[nodiscard]] inline T unmerge(T const& x, T const& y) const noexcept { + return x - y; + } + + [[nodiscard]] inline T sentinel() const noexcept { + return 0; + } + + [[nodiscard]] inline size_t g(size_t i) const noexcept { + return i | (i + 1); + } + + [[nodiscard]] inline size_t h(size_t i) const noexcept { + return i & (i + 1); + } + + std::vector tree; +}; + +void solve() { + int n, q; + cin >> n >> q; + + v coordinates; + + v salaries(n); + for (auto& salary : salaries) { + cin >> salary; + coordinates.eb(salary); + } + + v> queries; + + while (q--) { + char cmd; + int l, r; + cin >> cmd >> l >> r; + queries.eb(cmd, l, r); + if (cmd == '?') { + coordinates.eb(l); + } + coordinates.eb(r); + } + + sort(all(coordinates)); + coordinates.erase(unique(all(coordinates)), coordinates.end()); + + auto index = [&](int salary) { + return distance(coordinates.begin(), lower_bound(all(coordinates), salary)); + }; + + fenwick_tree fw(coordinates.size()); + for (auto salary : salaries) { + fw.update(index(salary), 1); + } + + for (auto& [cmd, a, b] : queries) { + if (cmd == '?') { + cout << fw.query(index(a), index(b)) << endl; + } else { + fw.update(index(salaries[a - 1]), -1); + salaries[a - 1] = b; + fw.update(index(salaries[a - 1]), 1); + } + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + cin.exceptions(cin.failbit); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/salary-queries-fenwick.in b/cses/range-queries/salary-queries-fenwick.in new file mode 100644 index 0000000..75bd0fd --- /dev/null +++ b/cses/range-queries/salary-queries-fenwick.in @@ -0,0 +1,12 @@ +10 10 +9 9 1 4 3 2 10 1 2 1 +? 1 5 +? 3 9 +? 2 5 +! 5 1 +? 2 5 +? 2 4 +? 3 10 +? 2 6 +? 7 7 +? 3 7 diff --git a/cses/range-queries/salary-queries-fenwick.out b/cses/range-queries/salary-queries-fenwick.out new file mode 100644 index 0000000..13fa4e9 --- /dev/null +++ b/cses/range-queries/salary-queries-fenwick.out @@ -0,0 +1,12 @@ +7 +4 +4 +3 +3 +4 +3 +0 +1 + +[code]: 0 +[time]: 14.2241 ms \ No newline at end of file diff --git a/cses/range-queries/salary-queries-pbds.cc b/cses/range-queries/salary-queries-pbds.cc new file mode 100644 index 0000000..e2a8016 --- /dev/null +++ b/cses/range-queries/salary-queries-pbds.cc @@ -0,0 +1,197 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +[[nodiscard]] static T MIN() { + return std::numeric_limits::min(); +} + +template +[[nodiscard]] static T MAX() { + return std::numeric_limits::max(); +} + +template +[[nodiscard]] static T sc(auto &&x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto &&x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +#include +#include + +using namespace __gnu_pbds; + +// https://mirror.codeforces.com/blog/entry/124683 + +namespace hashing { +using i64 = std::int64_t; +using u64 = std::uint64_t; +static const u64 FIXED_RANDOM = + std::chrono::steady_clock::now().time_since_epoch().count(); + +#if USE_AES +std::mt19937 rd(FIXED_RANDOM); +const __m128i KEY1{(i64)rd(), (i64)rd()}; +const __m128i KEY2{(i64)rd(), (i64)rd()}; +#endif + +template +struct custom_hash {}; + +template +inline void hash_combine(u64 &seed, T const &v) { + custom_hash hasher; + seed ^= hasher(v) + 0x9e3779b97f4a7c15 + (seed << 12) + (seed >> 4); +}; + +template +struct custom_hash::value>::type> { + u64 operator()(T _x) const { + u64 x = _x; +#if USE_AES + __m128i m{i64(u64(x) * 0xbf58476d1ce4e5b9u64), (i64)FIXED_RANDOM}; + __m128i y = _mm_aesenc_si128(m, KEY1); + __m128i z = _mm_aesenc_si128(y, KEY2); + return z[0]; +#else + x += 0x9e3779b97f4a7c15 + FIXED_RANDOM; + x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; + x = (x ^ (x >> 27)) * 0x94d049bb133111eb; + return x ^ (x >> 31); +#endif + } +}; + +template +struct custom_hash()))>> { + u64 operator()(T const &a) const { + u64 value = FIXED_RANDOM; + for (auto &x : a) + hash_combine(value, x); + return value; + } +}; + +template +struct custom_hash> { + u64 operator()(const std::tuple &a) const { + u64 value = FIXED_RANDOM; + std::apply( + [&value](T const &...args) { + (hash_combine(value, args), ...); + }, + a); + return value; + } +}; + +template +struct custom_hash> { + u64 operator()(std::pair const &a) const { + u64 value = FIXED_RANDOM; + hash_combine(value, a.first); + hash_combine(value, a.second); + return value; + } +}; +}; // namespace hashing + +#ifdef PB_DS_ASSOC_CNTNR_HPP +template +using hashtable = gp_hash_table< + Key, Value, hashing::custom_hash, std::equal_to, + direct_mask_range_hashing<>, linear_probe_fn<>, + hash_standard_resize_policy, + hash_load_check_resize_trigger<>, true>>; + +#endif +#ifdef PB_DS_TREE_POLICY_HPP +template +using multitree = tree, rb_tree_tag, + tree_order_statistics_node_update>; +template +using rbtree = tree, rb_tree_tag, + tree_order_statistics_node_update>; +#endif + +void solve() { + int n, q; + cin >> n >> q; + hashtable id_to_salary; + rbtree> tree; + + int salary; + for (int i = 0; i < n; ++i) { + cin >> salary; + id_to_salary[i] = salary; + tree.insert({salary, i}); + } + + char cmd; + int l, r, i; + while (q--) { + cin >> cmd; + if (cmd == '?') { + cin >> l >> r; + int ans = tree.order_of_key({r + 1, 0}) - tree.order_of_key({l, 0}); + cout << ans << endl; + } else { + cin >> i >> salary; + --i; + tree.erase({id_to_salary[i], i}); + id_to_salary[i] = salary; + tree.insert({salary, i}); + } + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + cin.exceptions(cin.failbit); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/salary-queries-pbds.in b/cses/range-queries/salary-queries-pbds.in new file mode 100644 index 0000000..f8b1627 --- /dev/null +++ b/cses/range-queries/salary-queries-pbds.in @@ -0,0 +1,12 @@ +10 10 +5 2 8 7 1 1 2 6 3 1 +? 1 3 +? 2 3 +? 1 4 +! 9 10 +? 6 6 +! 3 3 +? 1 5 +! 6 2 +? 4 10 +? 6 10 diff --git a/cses/range-queries/salary-queries-pbds.out b/cses/range-queries/salary-queries-pbds.out new file mode 100644 index 0000000..3d0ec9d --- /dev/null +++ b/cses/range-queries/salary-queries-pbds.out @@ -0,0 +1,10 @@ +6 +3 +6 +1 +7 +4 +3 + +[code]: 0 +[time]: 14.5617 ms \ No newline at end of file diff --git a/cses/range-queries/static-range-minimum-queries.cc b/cses/range-queries/static-range-minimum-queries.cc new file mode 100644 index 0000000..40fefd3 --- /dev/null +++ b/cses/range-queries/static-range-minimum-queries.cc @@ -0,0 +1,111 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct sparse_table { + sparse_table(std::vector const& ts) + : table(floor(__lg(max(1, static_cast(ts.size())))) + 1, + std::vector(ts.size())) { + for (size_t i = 0; i < ts.size(); ++i) { + table[0][i] = ts[i]; + } + + for (size_t j = 1; j < table.size(); ++j) { + for (size_t i = 0; i + (1 << (j - 1)) < ts.size(); ++i) { + table[j][i] = merge(table[j - 1][i], table[j - 1][i + (1 << (j - 1))]); + } + } + } + + [[nodiscard]] T query(size_t const l, size_t const r) const { + if (!(0 <= l && r < table[0].size())) { + return 0; + } + + int k = floor(__lg(r - l + 1)); + return merge(table[k][l], table[k][r - (1 << k) + 1]); + } + + private: + [[nodiscard]] inline T merge(T const& x, T const& y) const noexcept { + return min(x, y); + } + + std::vector> table; +}; + +void solve() { + int n, q; + cin >> n >> q; + v a(n); + for (auto& e : a) + cin >> e; + sparse_table st(a); + while (q--) { + int l, r; + cin >> l >> r; + --l; + --r; + cout << st.query(l, r) << endl; + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/static-range-minimum-queries.in b/cses/range-queries/static-range-minimum-queries.in new file mode 100644 index 0000000..98badeb --- /dev/null +++ b/cses/range-queries/static-range-minimum-queries.in @@ -0,0 +1,6 @@ +8 4 +3 2 4 5 1 1 5 3 +2 4 +5 6 +1 8 +3 3 diff --git a/cses/range-queries/static-range-minimum-queries.out b/cses/range-queries/static-range-minimum-queries.out new file mode 100644 index 0000000..a90d208 --- /dev/null +++ b/cses/range-queries/static-range-minimum-queries.out @@ -0,0 +1,7 @@ +2 +1 +1 +4 + +[code]: 0 +[time]: 7.20024 ms \ No newline at end of file diff --git a/cses/range-queries/static-sum-range-queries.cc b/cses/range-queries/static-sum-range-queries.cc new file mode 100644 index 0000000..7d5625e --- /dev/null +++ b/cses/range-queries/static-sum-range-queries.cc @@ -0,0 +1,154 @@ +#include // {{{ + +// https://codeforces.com/blog/entry/96344 + +#pragma GCC optimize("O2,unroll-loops") +#pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") + +using namespace std; + +template +constexpr T MIN = std::numeric_limits::min(); + +template +constexpr T MAX = std::numeric_limits::max(); + +template +[[nodiscard]] static T sc(auto&& x) { + return static_cast(x); +} + +template +[[nodiscard]] static T sz(auto&& x) { + return static_cast(x.size()); +} + +#define prln(...) std::println(__VA_ARGS__) +#define pr(...) std::print(__VA_ARGS__) + +#ifdef LOCAL +#define dbgln(...) std::println(__VA_ARGS__) +#define dbg(...) std::print(__VA_ARGS__) +#endif + +using ll = long long; +using ld = long double; +template +using v = std::vector; +template +using r = std::array; +template +using p = std::pair; + +#define ff first +#define ss second +#define eb emplace_back +#define pb push_back +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +// }}} + +template +struct fenwick_tree { + public: + explicit fenwick_tree(std::vector const& ts) : tree(ts.size()) { + for (size_t i = 0; i < ts.size(); ++i) { + tree[i] = ts[i]; + } + for (size_t i = 0; i < tree.size(); ++i) { + size_t j = g(i); + if (j < tree.size()) { + tree[j] += tree[i]; + } + } + } + + T const query(size_t i) const { + if (!(0 <= i && i < tree.size())) { + throw std::out_of_range(std::format( + "cannot query fenwick tree of size {} at index {}", tree.size(), i)); + } + + T t = sentinel(); + + for (int j = static_cast(i); j >= 0; j = h(j) - 1) { + t = merge(t, tree[j]); + } + + return t; + }; + + T const query(size_t l, size_t r) const { + if (!(0 <= l && r < tree.size())) { + throw std::out_of_range( + std::format("cannot query fenwick tree of size {} at range [{}, {}]", + tree.size(), l, r)); + } + + if (l == 0) { + return query(r); + } + + return unmerge(query(r), query(l - 1)); + }; + + void update(size_t i, T const& t) noexcept { + assert(0 <= i && t < tree.size()); + + for (size_t j = i; j < tree.size(); j = g(j)) { + tree[j] = merge(tree[j], t); + } + } + + private: + [[nodiscard]] inline T merge(T const& x, T const& y) const noexcept { + return x + y; + } + + [[nodiscard]] inline T unmerge(T const& x, T const& y) const noexcept { + return x - y; + } + + [[nodiscard]] inline T sentinel() const noexcept { + return 0; + } + + [[nodiscard]] inline size_t g(size_t i) const noexcept { + return i | (i + 1); + } + + [[nodiscard]] size_t h(size_t i) const noexcept { + return i & (i + 1); + } + + std::vector tree; +}; + +void solve() { + int n, q; + cin >> n >> q; + v a(n); + for (auto& e : a) + cin >> e; + fenwick_tree fw(a); + while (q--) { + ll l, r; + cin >> l >> r; + --l; + --r; + cout << fw.query(l, r) << endl; + } +} + +int main() { // {{{ + cin.tie(nullptr)->sync_with_stdio(false); + + int t = 1; + // cin >> t; + while (t--) { + solve(); + } + + return 0; +} +// }}} diff --git a/cses/range-queries/static-sum-range-queries.in b/cses/range-queries/static-sum-range-queries.in new file mode 100644 index 0000000..98badeb --- /dev/null +++ b/cses/range-queries/static-sum-range-queries.in @@ -0,0 +1,6 @@ +8 4 +3 2 4 5 1 1 5 3 +2 4 +5 6 +1 8 +3 3 diff --git a/cses/range-queries/static-sum-range-queries.out b/cses/range-queries/static-sum-range-queries.out new file mode 100644 index 0000000..390c3ef --- /dev/null +++ b/cses/range-queries/static-sum-range-queries.out @@ -0,0 +1,7 @@ +11 +2 +24 +4 + +[code]: 0 +[time]: 13.4346 ms \ No newline at end of file