Skip to content

Commit

Permalink
perf: simplify
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiphereth-A committed Dec 19, 2024
1 parent 2d58fba commit 3dfe0fd
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 24 deletions.
22 changes: 13 additions & 9 deletions src/code/ds/rus4_st.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

namespace tifa_libs::ds {

template <class T, auto op, T (*e)()>
requires std::same_as<std::remove_cvref_t<decltype(op(T(), T()))>, T>
template <class T, auto op>
class rus4_st {
u32 sz, B;
st_array<T, op, e> st;
vec<st_array<T, op, e>> d;
st_array<T, op> st;
vec<st_array<T, op>> d;

public:
CEXPE rus4_st(spn<T> a) : rus4_st(a, (u32)std::bit_width(a.size())) {}
CEXP rus4_st(spn<T> a, u32 block_size) { reset(a, block_size); }

CEXP void reset(spn<T> a, u32 block_size) {
Expand All @@ -23,13 +23,17 @@ class rus4_st {
}
CEXP u32 CR block_size() const { return B; }
CEXP u32 CR size() const { return sz; }
//! 0-indexed
CEXP T query(u32 l = 0) const { return query(l, sz); }
//! 0-indexed, [l, r]
CEXP T query(u32 l = 0) const { return query(l, size()); }
//! 0-indexed, [l, r)
CEXP T query(u32 l, u32 r) const {
if (r <= l) return e();
assert(l < r && r <= size());
if (u32 L = l / B, R = r / B; L == R) return d[L].query(l % B, r % B);
else return op(op(d[L].query(l % B), st.query(L + 1, R)), d[R].query(0, r % B));
else {
T ret = d[L].query(l % B);
if (L + 1 != R) ret = op(ret, st.query(L + 1, R));
if (r % B) ret = op(ret, d[R].query(0, r % B));
return ret;
}
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/code/ds/segtree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ requires requires(T val, T new_val, F tag, F new_tag) {
{ id() } -> std::same_as<F>;
}
class segtree {
const T E = e();
const F ID = id();
static inline const T E = e();
static inline const F ID = id();
u32 sz, lbn, n;
vec<T> val;
vec<F> tag;
Expand All @@ -24,7 +24,7 @@ class segtree {
public:
template <class V>
CEXPE segtree(V &&a) { reset(std::forward<V>(a)); }
CEXPE segtree(u32 n = 0) : segtree(vec<T>(n, e())) {}
CEXPE segtree(u32 n = 0) : segtree(vec<T>(n, E)) {}

template <class V>
CEXP void reset(V &&a) {
Expand Down
11 changes: 6 additions & 5 deletions src/code/ds/st_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace tifa_libs::ds {

template <class T, auto op, T (*e)()>
template <class T, auto op>
requires std::same_as<std::remove_cvref_t<decltype(op(T(), T()))>, T>
class st_array {
vvec<T> st;
Expand All @@ -16,7 +16,7 @@ class st_array {

CEXP void reset(spn<T> a) {
const u32 n = (u32)a.size(), lbn = (u32)std::bit_width(n);
st = vvec<T>(lbn, vec<T>(n, e())), std::ranges::copy(a, st[0].begin());
st = vvec<T>(lbn, vec<T>(n)), std::ranges::copy(a, st[0].begin());
flt_ (u32, j, 1, lbn)
flt_ (u32, i, 0, n) st[j][i] = op(st[j - 1][i], st[j - 1][(u32)max(0, i32(i - (1 << (j - 1))))]);
}
Expand All @@ -27,16 +27,17 @@ class st_array {
}
const u32 n = size() + 1, lbn = (u32)std::bit_width(n);
if (st[0].push_back(x); std::has_single_bit(n)) {
st.emplace_back(n - 1, e());
st.emplace_back(n - 1);
flt_ (u32, i, 0, n - 1) st.back()[i] = op(st[lbn - 2][i], st[lbn - 2][(u32)max(0, i32(i - (1 << (lbn - 2))))]);
}
flt_ (u32, j, 1, lbn) st[j].push_back(op(st[j - 1].back(), st[j - 1][n - 1 - (1 << (j - 1))]));
}
CEXP u32 height() const { return (u32)st.size(); }
CEXP u32 size() const { return (u32)st[0].size(); }
CEXP u32 size() const { return height() ? (u32)st[0].size() : 0; }
CEXP T query(u32 l = 0) const { return query(l, size()); }
//! 0-indexed, [l, r)
CEXP T query(u32 l, u32 r) const {
if (r <= l) return e();
assert(l < r && r <= size());
const u32 k = (u32)(std::bit_width(r - l) - 1);
return op(st[k][l + (1 << k) - 1], st[k][r - 1]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#include "../../code/ds/rus4_st.hpp"

i32 f(i32 x, i32 y) { return tifa_libs::min(x, y); }
i32 e() { return std::numeric_limits<i32>::max(); }

int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
Expand All @@ -12,13 +11,13 @@ int main() {
veci a(n);
flt_ (u32, i, 0, n) std::cin >> a[i];
if (n < 16) {
tifa_libs::ds::st_array<i32, f, e> st(a);
tifa_libs::ds::st_array<i32, f> st(a);
for (u32 i = 1, u, v; i <= q; ++i) {
std::cin >> u >> v;
std::cout << st.query(u, v) << '\n';
}
} else {
tifa_libs::ds::rus4_st<i32, f, e> st(a, (u32)std::bit_width(n));
tifa_libs::ds::rus4_st<i32, f> st(a);
for (u32 i = 1, u, v; i <= q; ++i) {
std::cin >> u >> v;
std::cout << st.query(u, v) << '\n';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
#include "../../code/ds/st_array.hpp"

i32 f(i32 x, i32 y) { return tifa_libs::min(x, y); }
i32 e() { return std::numeric_limits<i32>::max(); }

int main() {
std::cin.tie(nullptr)->std::ios::sync_with_stdio(false);
u32 n, q;
std::cin >> n >> q;
veci a(n);
flt_ (u32, i, 0, n) std::cin >> a[i];
tifa_libs::ds::st_array<i32, f, e> st(a);
tifa_libs::ds::st_array<i32, f> st(a);
for (u32 i = 1, u, v; i <= q; ++i) {
std::cin >> u >> v;
std::cout << st.query(u, v) << '\n';
Expand Down
3 changes: 1 addition & 2 deletions src/test_cpverifier/unit-test/ds/st_array.bzoj1012.test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@
#include "../base.hpp"

i64 f(i64 x, i64 y) { return tifa_libs::max(x, y); }
i64 e() { return 0; }

void test(strn CR data) {
auto [fn_in, fn_ans] = tifa_libs::unittest::get_fname_in_ans("bzoj", "1012", data);
std::ifstream fin(fn_in), fans(fn_ans);

u32 m, d;
fin >> m >> d;
tifa_libs::ds::st_array<i64, f, e> st;
tifa_libs::ds::st_array<i64, f> st;
char op;
i64 t = 0, u;
for (u32 i = 1; i <= m; ++i) {
Expand Down

0 comments on commit 3dfe0fd

Please sign in to comment.