Skip to content

Commit

Permalink
add digit dp; fast treekc; avl/segtree bug fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
old-yan committed Sep 25, 2024
1 parent 944eec2 commit 0959aa6
Show file tree
Hide file tree
Showing 55 changed files with 1,543 additions and 94 deletions.
6 changes: 3 additions & 3 deletions DS/AVL.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,17 +475,17 @@ namespace OY {
void insert_node_by_key(node *ptr) { ptr->m_hi = ptr->m_sz = 1, _insert(&m_rt, ptr - _ptr(0), ValueLessJudger(ptr->get())); }
void insert_node_by_rank(node *ptr, size_type k) { ptr->m_hi = ptr->m_sz = 1, _insert(&m_rt, ptr - _ptr(0), RankJudger(k)); }
template <typename Modify = Ignore>
void insert_by_key(const key_type &key, Modify &&modify = Modify()) { _insert(&m_rt, _newnode(key, modify), ValueLessJudger(key)); }
void insert_by_key(key_type key, Modify &&modify = Modify()) { _insert(&m_rt, _newnode(key, modify), ValueLessJudger(key)); }
template <typename Modify = Ignore>
void insert_by_rank(const key_type &key, size_type k, Modify &&modify = Modify()) { _insert(&m_rt, _newnode(key, modify), RankJudger(k)); }
void insert_by_rank(key_type key, size_type k, Modify &&modify = Modify()) { _insert(&m_rt, _newnode(key, modify), RankJudger(k)); }
bool erase_by_key(const key_type &key) { return _erase_by_key(&m_rt, key); }
void erase_by_rank(size_type k) { _erase_by_rank(&m_rt, k); }
template <typename Modify>
bool modify_by_key(const key_type &key, Modify &&modify) { return _modify_by_key(m_rt, key, modify); }
template <typename Modify>
void modify_by_rank(size_type k, Modify &&modify) { _modify_by_rank(m_rt, k, modify); }
template <typename Modify>
bool modify_or_insert(const key_type &key, Modify &&modify) { return _modify_or_insert(&m_rt, key, modify); }
bool modify_or_insert(key_type key, Modify &&modify) { return _modify_or_insert(&m_rt, key, modify); }
tree_type split_by_key(const key_type &key) {
tree_type other;
_split(m_rt, &m_rt, &other.m_rt, ValueLessEqualJudger(key));
Expand Down
6 changes: 5 additions & 1 deletion DS/MonoBIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ namespace OY {
using size_type = uint32_t;
inline size_type lowbit(size_type x) { return x & -x; }
inline size_type meet(size_type a, size_type b) { return ((a + 1) & -(size_type(1) << std::bit_width((a + 1) ^ (b + 1)))) - 1; }
struct Self {
template <typename Tp>
Tp operator()(const Tp &x) const { return x; }
};
template <typename Tp, Tp Identity, typename Operation>
struct BaseCommutativeMonoid {
using value_type = Tp;
Expand Down Expand Up @@ -132,7 +136,7 @@ namespace OY {
template <typename Tp, Tp ZeroMask = 0>
using MonoBitOrBIT = MONOBIT::Tree<MONOBIT::BaseCommutativeMonoid<Tp, ZeroMask, std::bit_or<Tp>>>;
template <typename Tp, Tp ZeroMask = 0>
using MonoBitXorBIT = MONOBIT::Tree<MONOBIT::BaseCommutativeGroup<Tp, ZeroMask, std::bit_xor<Tp>, std::bit_not<Tp>>>;
using MonoBitXorBIT = MONOBIT::Tree<MONOBIT::BaseCommutativeGroup<Tp, ZeroMask, std::bit_xor<Tp>, MONOBIT::Self>>;
template <typename Tp, Tp Zero = Tp()>
using MonoSumBIT = MONOBIT::Tree<MONOBIT::BaseCommutativeGroup<Tp, Zero, std::plus<Tp>, std::negate<Tp>>>;
}
Expand Down
6 changes: 5 additions & 1 deletion DS/SegBIT.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ namespace OY {
inline SizeType lowbit(SizeType x) { return x & -x; }
template <typename SizeType>
inline SizeType meet(SizeType a, SizeType b) { return ((a + 1) & -(SizeType(1) << std::bit_width((a + 1) ^ (b + 1)))) - 1; }
struct Self {
template <typename Tp>
Tp operator()(const Tp &x) const { return x; }
};
template <typename Tp, Tp Identity, typename Operation>
struct BaseMonoid {
using value_type = Tp;
Expand Down Expand Up @@ -204,7 +208,7 @@ namespace OY {
template <typename Tp, Tp ZeroMask = 0, typename SizeType = uint64_t>
using VectorSEGBITOrSegBIT = SEGBIT::Tree<SEGBIT::BaseMonoid<Tp, ZeroMask, std::bit_or<Tp>>, SizeType>;
template <typename Tp, Tp ZeroMask = 0, typename SizeType = uint64_t>
using VectorSEGBITXorSegBIT = SEGBIT::Tree<SEGBIT::BaseGroup<Tp, ZeroMask, std::bit_xor<Tp>, std::bit_not<Tp>>, SizeType>;
using VectorSEGBITXorSegBIT = SEGBIT::Tree<SEGBIT::BaseGroup<Tp, ZeroMask, std::bit_xor<Tp>, SEGBIT::Self>, SizeType>;
template <typename Tp, Tp Zero = Tp(), typename SizeType = uint64_t>
using VectorSumSegBIT = SEGBIT::Tree<SEGBIT::BaseGroup<Tp, Zero, std::plus<Tp>, std::negate<Tp>>, SizeType>;
}
Expand Down
2 changes: 1 addition & 1 deletion DS/SegTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ namespace OY {
if constexpr (Has_get_lazy<node>::value) {
if constexpr (Has_has_lazy<node>::value)
if (!q->has_lazy()) return;
node::com(q->get_lazy(), cur);
node::com(q->get_lazy(), _ptr(cur));
}
} else
func(p, q);
Expand Down
18 changes: 16 additions & 2 deletions DS/WTree.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
最后修改:
20240328
20240922
测试环境:
gcc11.2,c++17
clang12.0,C++17
Expand All @@ -18,15 +18,21 @@ namespace OY {
struct Plus {
template <typename Tp1, typename Tp2>
void operator()(Tp1 &a, const Tp2 &b) const { a += b; }
template <typename Tp>
void operator()(Tp &a) const { a = -a; }
};
struct BitXor {
template <typename Tp1, typename Tp2>
void operator()(Tp1 &a, const Tp2 &b) const { a ^= b; }
template <typename Tp>
void operator()(Tp &a) const {}
};
template <typename Tp, typename Operation = Plus>
class Tree {
public:
static constexpr size_type Z = 64, W = Z / sizeof(Tp), b = __builtin_ctz(W);
typedef Tp vec_type __attribute((vector_size(Z / 2)));
private:
static constexpr size_type _calc_height(size_type n) { return n <= W ? 1 : _calc_height((n + W - 1) / W) + 1; }
static constexpr size_type _calc_offset(size_type h, size_type len) {
size_type s = 0, n = len + 1;
Expand Down Expand Up @@ -97,7 +103,11 @@ namespace OY {
for (size_type h = 0; h != m_height; h++) Operation()(res, m_data[m_offset[h] + (i + 1 >> (h * b))]);
return res;
}
Tp query(size_type left, size_type right) const { return presum(right) - presum(left - 1); }
Tp query(size_type left, size_type right) const {
auto vl = presum(left - 1), vr = presum(right);
Operation()(vl), Operation()(vr, vl);
return vr;
}
Tp query_all() const { return presum(m_size - 1); }
void add(size_type i, const Tp &inc) {
vec_type v{};
Expand All @@ -120,6 +130,10 @@ namespace OY {
return out << "]";
}
}
template <typename Tp>
using WSumTree = WTree::Tree<Tp, WTree::Plus>;
template <typename Tp>
using WXorTree = WTree::Tree<Tp, WTree::BitXor>;
}

#endif
4 changes: 2 additions & 2 deletions DS/WTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ void test_xor() {
// 输出前缀和
cout << "presum(3) = " << T.presum(3) << endl;
cout << "presum(2) = " << T.presum(2) << endl;
// 利用差分查询 3 处的值
cout << "query(3) = " << (T.presum(3) ^ T.presum(2)) << endl;
// 查询 3 处的值
cout << "query(3) = " << T.query(3, 3) << endl;
cout << endl;
}

Expand Down
11 changes: 6 additions & 5 deletions GRAPH/Psuedotree_ig.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
3. [2360. 图中的最长环](https://leetcode.cn/problems/longest-cycle-in-a-graph/)
4. [2836. 在传球游戏中最大化函数值](https://leetcode.cn/problems/maximize-value-of-function-in-a-ball-passing-game/)
5. [P2607 [ZJOI2008] 骑士](https://www.luogu.com.cn/problem/P2607)
6. [P2921 [USACO08DEC] Trick or Treat on the Farm G](https://www.luogu.com.cn/problem/P2921)
7. [P3533 [POI2012] RAN-Rendezvous](https://www.luogu.com.cn/problem/P3533)
8. [P3651 展翅翱翔之时 (はばたきのとき)](https://www.luogu.com.cn/problem/P3651)
9. [P7981 [JRKSJ R3] system](https://www.luogu.com.cn/problem/P7981)
10. [爱探险的朵拉](https://ac.nowcoder.com/acm/problem/276008)
6. [P2661 [NOIP2015 提高组] 信息传递](https://www.luogu.com.cn/problem/P2661)
7. [P2921 [USACO08DEC] Trick or Treat on the Farm G](https://www.luogu.com.cn/problem/P2921)
8. [P3533 [POI2012] RAN-Rendezvous](https://www.luogu.com.cn/problem/P3533)
9. [P3651 展翅翱翔之时 (はばたきのとき)](https://www.luogu.com.cn/problem/P3651)
10. [P7981 [JRKSJ R3] system](https://www.luogu.com.cn/problem/P7981)
11. [爱探险的朵拉](https://ac.nowcoder.com/acm/problem/276008)


### 二、模板功能
Expand Down
2 changes: 1 addition & 1 deletion MATH/HamelXorBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace OY {
size_type MaskNodes<Tp, 0>::s_width = sizeof(Tp) << 3;
template <typename Tp, size_type MAX_WIDTH>
struct HamelXorBase {
MaskNodes<Tp, MAX_WIDTH> m_masks;
MaskNodes<Tp, MAX_WIDTH> m_masks{};
static void set_width(size_type w) {
static_assert(!MAX_WIDTH, "MAX_WIDTH Must Be 0");
MaskNodes<Tp, MAX_WIDTH>::s_width = w;
Expand Down
189 changes: 189 additions & 0 deletions MISC/DigitDP.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
最后修改:
20240924
测试环境:
gcc11.2,c++14
clang12.0,C++14
msvc14.2,C++14
*/
#ifndef __OY_DIGITDP__
#define __OY_DIGITDP__

#include <algorithm>
#include <array>
#include <cstdint>
#include <map>
#include <numeric>
#include <string>
#include <vector>

namespace OY {
namespace DIGITDP {
using size_type = uint32_t;
template <uint32_t Base>
struct IntegerString {
std::vector<uint32_t> m_str;
IntegerString() = default;
IntegerString(uint64_t val) {
do m_str.push_back(val % Base), val /= Base;
while (val);
}
size_type size() const { return m_str.size(); }
void assign(size_type n) { m_str.assign(n, 0); }
uint32_t get(size_type i) const { return m_str[i]; }
void set(size_type i, uint32_t val) { m_str[i] = val; }
void push_high(uint32_t val) { m_str.push_back(val); }
void pop_high() { m_str.pop_back(); }
operator uint64_t() const {
uint64_t val = 0;
for (size_type i = size() - 1; ~i; i--) val = val * Base + get(i);
return val;
}
};
template <>
struct IntegerString<10> {
std::string m_str;
IntegerString() = default;
IntegerString(uint64_t val) {
do m_str += '0' + val % 10, val /= 10;
while (val);
}
IntegerString(std::string str) : m_str(str.rbegin(), str.rend()) {}
explicit IntegerString(const char *str) : IntegerString(std::string(str)) {}
size_type size() const { return m_str.size(); }
void assign(size_type n) { m_str.assign(n, '0'); }
uint32_t get(size_type i) const { return m_str[i] - '0'; }
void set(size_type i, uint32_t val) { m_str[i] = '0' + val; }
void push_high(uint32_t val) { m_str += '0' + val; }
void pop_high() { m_str.pop_back(); }
operator std::string() const { return std::string(m_str.rbegin(), m_str.rend()); }
operator uint64_t() const {
uint64_t val = 0;
for (size_type i = size() - 1; ~i; i--) val = val * 10 + get(i);
return val;
}
};
template <uint32_t Base>
IntegerString<Base> prev_number(IntegerString<Base> s) {
size_type n = s.size(), i = 0;
while (i != n && !s.get(i)) s.set(i++, Base - 1);
s.set(i, s.get(i) - 1);
if (n > 1 && i == n - 1 && !s.get(i)) s.pop_high();
return s;
}
template <uint32_t Base>
IntegerString<Base> next_number(IntegerString<Base> s) {
size_type n = s.size(), i = 0;
while (i != n && s.get(i) == Base - 1) s.set(i++, 0);
if (i == n)
s.push_high(1);
else
s.set(i, s.get(i) + 1);
return s;
}
template <typename Tp, uint32_t Base, bool Trace>
struct Tracer {};
template <typename Tp, uint32_t Base>
struct Tracer<Tp, Base, true> {
std::vector<std::vector<std::vector<std::pair<uint32_t, uint32_t>>>> m_from;
IntegerString<Base> m_str;
void init(uint32_t state_count, IntegerString<Base> number) {
m_str = number;
m_from.assign(number.size(), std::vector<std::vector<std::pair<uint32_t, uint32_t>>>(state_count));
}
void add_trace(uint32_t state, uint32_t prev_state, size_type prev_len, uint32_t c) { m_from[prev_len][state].emplace_back(prev_state, c); }
template <typename Callback>
void _dfs(size_type idx, uint32_t state, bool equal, IntegerString<Base> &str, Callback &&call) {
if (!~idx)
call(str);
else {
for (auto &prev_state_c : m_from[idx][state]) {
auto prev_state = prev_state_c.first;
auto c = prev_state_c.second;
if (equal && c > m_str.get(idx)) continue;
if (!c && idx == str.size() - 1 && idx) continue;
str.set(idx, c);
_dfs(idx - 1, prev_state, equal && c == m_str.get(idx), str, call);
}
}
}
template <typename Callback>
void enumerate(uint32_t state, size_type len, Callback &&call) {
IntegerString<Base> str;
str.assign(len);
_dfs(len - 1, state, len == m_str.size(), str, call);
}
};
template <typename Tp, uint32_t Base, bool Trace = false>
struct Solver : Tracer<Tp, Base, Trace> {
using base_type = Tracer<Tp, Base, Trace>;
size_type n;
std::vector<std::array<Tp, 2>> dp, dp2;
template <typename Transfer, typename PlusCallback, typename MinusCallback>
void _solve_callback(IntegerString<Base> number, uint32_t state_count, Transfer &&transfer, PlusCallback &&plus, MinusCallback &&minus) {
n = number.size(), dp.assign(state_count, {}), dp2.assign(state_count, {});
if constexpr (Trace) base_type::init(state_count, number);
for (uint32_t c = 0; c != Base; c++) {
uint32_t state = transfer(-1, 0, c);
if (!~state) continue;
dp[state][c > number.get(0)]++;
if constexpr (Trace) base_type::add_trace(state, -1, 0, c);
if (c) continue;
if (n - 1)
for (uint32_t state = 0; state != state_count; state++) minus(dp[state][0] + dp[state][1], state, 1);
else
for (uint32_t state = 0; state != state_count; state++) minus(dp[state][0], state, 1);
}
if (n - 1)
for (uint32_t state = 0; state != state_count; state++) plus(dp[state][0] + dp[state][1], state, 1);
else
for (uint32_t state = 0; state != state_count; state++) plus(dp[state][0], state, 1);
for (size_type i = 1; i != n; i++) {
uint32_t cur = number.get(i);
dp.swap(dp2);
dp.assign(state_count, {});
for (uint32_t c = 0; c != Base; c++) {
for (uint32_t state = 0; state != state_count; state++)
if (dp2[state][0] || dp2[state][1]) {
uint32_t state2 = transfer(state, i, c);
if (~state2) {
dp[state2][c > cur] += dp2[state][0], dp[state2][c >= cur] += dp2[state][1];
if constexpr (Trace) base_type::add_trace(state2, state, i, c);
}
}
if (!c)
if (i + 1 < n)
for (uint32_t state = 0; state != state_count; state++) minus(dp[state][0] + dp[state][1], state, i + 1);
else
for (uint32_t state = 0; state != state_count; state++) minus(dp[state][0], state, i + 1);
}
if (i + 1 < n)
for (uint32_t state = 0; state != state_count; state++) plus(dp[state][0] + dp[state][1], state, i + 1);
else
for (uint32_t state = 0; state != state_count; state++) plus(dp[state][0], state, i + 1);
}
}
template <typename Transfer, typename ValueMapping>
Tp solve(IntegerString<Base> number, uint32_t state_count, Transfer &&transfer, ValueMapping &&mapping) {
Tp ans{};
auto plus = [&](Tp cnt, uint32_t state, size_type len) { ans += cnt * mapping(state, len); };
auto minus = [&](Tp cnt, uint32_t state, size_type len) { ans -= cnt * mapping(state, len); };
_solve_callback(std::move(number), state_count, transfer, plus, minus);
return ans;
}
template <typename ValueMapping, typename Callback>
void enumerate(ValueMapping &&mapping, Callback &&call) {
static_assert(Trace, "Trace Must Be True");
uint32_t state_count = dp.size();
for (size_type len = 1; len <= this->m_str.size(); len++)
for (uint32_t state = 0; state != state_count; state++)
if (this->m_from[len - 1][state].size() && mapping(state, len)) base_type::enumerate(state, len, call);
}
};
using IntStr10 = IntegerString<10>;
IntStr10 prev_number_base10(std::string s) { return prev_number<10>(IntStr10(std::move(s))); }
IntStr10 next_number_base10(std::string s) { return next_number<10>(IntStr10(std::move(s))); }
}
}

#endif
Loading

0 comments on commit 0959aa6

Please sign in to comment.