Skip to content

Commit

Permalink
mapped monozkw;
Browse files Browse the repository at this point in the history
  • Loading branch information
old-yan committed Feb 9, 2025
1 parent edf99bf commit f58da5b
Show file tree
Hide file tree
Showing 13 changed files with 326 additions and 10 deletions.
5 changes: 3 additions & 2 deletions DS/LichaoSegTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

1. [P4097 【模板】李超线段树 / [HEOI2013] Segment](https://www.luogu.com.cn/problem/P4097)
2. [P4655 [CEOI2017] Building Bridges](https://www.luogu.com.cn/problem/P4655)
3. [Line Add Get Min](https://judge.yosupo.jp/problem/line_add_get_min)(https://github.com/yosupo06/library-checker-problems/issues/174)
4. [Segment Add Get Min](https://judge.yosupo.jp/problem/segment_add_get_min)(https://github.com/yosupo06/library-checker-problems/issues/211)
3. [智乃的直线](https://ac.nowcoder.com/acm/problem/226924)
4. [Line Add Get Min](https://judge.yosupo.jp/problem/line_add_get_min)(https://github.com/yosupo06/library-checker-problems/issues/174)
5. [Segment Add Get Min](https://judge.yosupo.jp/problem/segment_add_get_min)(https://github.com/yosupo06/library-checker-problems/issues/211)

### 二、模板功能

Expand Down
4 changes: 0 additions & 4 deletions DS/LichaoSegTree_ex.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ namespace OY {
bool is_ascending() const { return m_k > 0; }
bool is_horizontal() const { return m_k == 0; }
};
struct BaseLess {
template <typename Tp>
bool operator()(const Tp &x, const Tp &y) const { return x < y; }
};
template <typename Tp, Tp BackGroundValue>
struct BaseJudger {
template <typename Line>
Expand Down
1 change: 1 addition & 0 deletions DS/LichaoSegTree_ex.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
​ 练习题目:

1. [P4069 [SDOI2016] 游戏](https://www.luogu.com.cn/problem/P4069)
2. [智乃的直线](https://ac.nowcoder.com/acm/problem/226924)

### 二、模板功能

Expand Down
1 change: 1 addition & 0 deletions DS/LichaoZkwTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
1. [P4097 【模板】李超线段树 / [HEOI2013] Segment](https://www.luogu.com.cn/problem/P4097)
2. [P4254 [JSOI2008] Blue Mary 开公司](https://www.luogu.com.cn/problem/P4254)
3. [P4655 [CEOI2017] Building Bridges](https://www.luogu.com.cn/problem/P4655)
4. [智乃的直线](https://ac.nowcoder.com/acm/problem/226924)

### 二、模板功能

Expand Down
4 changes: 0 additions & 4 deletions DS/LichaoZkwTree_ex.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@ namespace OY {
bool is_ascending() const { return m_k > 0; }
bool is_horizontal() const { return m_k == 0; }
};
struct BaseLess {
template <typename Tp>
bool operator()(const Tp &x, const Tp &y) const { return x < y; }
};
template <typename Tp, Tp BackGroundValue>
struct BaseJudger {
template <typename Line>
Expand Down
1 change: 1 addition & 0 deletions DS/LichaoZkwTree_ex.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
​ 练习题目:

1. [P4069 [SDOI2016] 游戏](https://www.luogu.com.cn/problem/P4069)
2. [智乃的直线](https://ac.nowcoder.com/acm/problem/226924)

### 二、模板功能

Expand Down
59 changes: 59 additions & 0 deletions DS/MappedMonoZkwTree.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
最后修改:
20250209
测试环境:
gcc11.2,c++11
clang22.0,C++11
msvc14.2,C++14
*/
#ifndef __OY_MAPPEDMONOZKWTREE__
#define __OY_MAPPEDMONOZKWTREE__

#include <queue>

#include "MonoZkwTree.h"

namespace OY {
namespace MMZKW {
using size_type = MONOZKW::size_type;
template <typename Tp, typename Compare, Tp Identity>
struct PqMapping {
using container_type = std::priority_queue<Tp, std::vector<Tp>, Compare>;
static Tp get(const container_type &bucket) {
if (bucket.empty()) return Identity;
return bucket.top();
}
};
template <typename Monoid, typename Mapping>
class Tree {
using inner_type = MONOZKW::Tree<Monoid>;
using container_type = typename Mapping::container_type;
inner_type m_zkw;
std::vector<container_type> m_buckets;
public:
Tree() = default;
Tree(size_type n) { resize(n); }
void resize(size_type n) {
m_buckets.clear(), m_buckets.reserve(n);
for(size_type i=0;i!=n;i++)m_buckets.emplace_back();
m_zkw.resize(n, [&](size_type i) { return Mapping::get(m_buckets[i]); });
}
container_type &operator[](size_type i) { return m_buckets[i]; }
const container_type &operator[](size_type i) const { return m_buckets[i]; }
void update(size_type i) { m_zkw.modify(i, Mapping::get(m_buckets[i])); }
auto query(size_type i) const -> decltype(m_zkw.query(i)) { return m_zkw.query(i); }
auto query(size_type left, size_type right) const -> decltype(m_zkw.query(left, right)) { return m_zkw.query(left, right); }
auto query_all() const -> decltype(m_zkw.query_all()) { return m_zkw.query_all(); }
template <typename Judger>
size_type max_right(size_type left, Judger &&judge) const { return m_zkw.max_right(left, judge); }
template <typename Judger>
size_type min_left(size_type right, Judger &&judge) const { return m_zkw.min_left(right, judge); }
};
}
template <typename Monoid, typename Tp, Tp Minimum = std::numeric_limits<Tp>::min()>
using MaxPqMonoZkwTree = MMZKW::Tree<Monoid, MMZKW::PqMapping<Tp, std::less<Tp>, Minimum>>;
template <typename Monoid, typename Tp, Tp Maximum = std::numeric_limits<Tp>::max()>
using MinPqMonoZkwTree = MMZKW::Tree<Monoid, MMZKW::PqMapping<Tp, std::greater<Tp>, Maximum>>;
}

#endif
55 changes: 55 additions & 0 deletions DS/MappedMonoZkwTree.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
### 一、模板类别

​ 数据结构: `MappedMonoZkw` 线段树。

​ 练习题目:

1. [弩蚊怒夏](https://ac.nowcoder.com/acm/problem/226861)
2. [小红的数组操作](https://ac.nowcoder.com/acm/problem/277952)

### 二、模板功能


​ 本模板基本类似 `MonoZkwTree` 。区别在于, `MonoZkw` 的叶结点处,只有一个普普通通的元素值;而 `MappedMonoZkw` 的叶结点处,可能并非一个普通元素值。可能是一个容器,由这个容器推出一个代表元素作为此叶结点处的值;也可能是一些别的类型的东西,经过计算得到元素值。

​ 通过 `Mapping` 模板参数,可以控制叶结点处的数据类型,以及计算叶结点的值的方法。默认的提供了 `MaxPqMonoZkwTree``MinPqMonoZkwTree` ,表示每个叶结点处有一个堆,由堆顶作为代表元素充当线段树的叶结点处的值。

### 三、模板示例

```c++
#include "DS/MappedMonoZkwTree.h"
#include "IO/FastIO.h"

void test() {
// 假如,有 10 个桶
// 查询 query(l, r) 表示查询 bucket[l~r] 这些桶的最大值的和
// 空桶的贡献是 0
using monoid = OY::MonoSumTree<int>::group;
OY::MaxPqMonoZkwTree<monoid, int, 0> S(10);
// 记得对桶做修改之后,要调用 S.update
S[2].push(25), S[2].push(50);
S.update(2);

S[4].push(30);
S.update(4);

S[5].push(100), S[5].push(8);
S.update(5);

S[8].push(88);
S.update(8);

cout << "S.query(4, 6) = " << S.query(4, 6) << endl;
}

int main() {
test();
}
```

```
#输出如下
S.query(4, 6) = 130
```

33 changes: 33 additions & 0 deletions TEST/local/MappedMonoZkwTree_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#include "DS/MappedMonoZkwTree.h"
#include "IO/FastIO.h"

void test() {
// 假如,有 10 个桶
// 查询 query(l, r) 表示查询 bucket[l~r] 这些桶的最大值的和
// 空桶的贡献是 0
using monoid = OY::MonoSumTree<int>::group;
OY::MaxPqMonoZkwTree<monoid, int, 0> S(10);
// 记得对桶做修改之后,要调用 S.update
S[2].push(25), S[2].push(50);
S.update(2);

S[4].push(30);
S.update(4);

S[5].push(100), S[5].push(8);
S.update(5);

S[8].push(88);
S.update(8);

cout << "S.query(4, 6) = " << S.query(4, 6) << endl;
}

int main() {
test();
}
/*
#输出如下
S.query(4, 6) = 130
*/
42 changes: 42 additions & 0 deletions TEST/oj/nc_226861.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "DS/MappedMonoZkwTree.h"
#include "IO/FastIO.h"

/*
[弩蚊怒夏](https://ac.nowcoder.com/acm/problem/226861)
*/
/**
* 上面的链接打不开
* 请换用这个链接 https://ac.nowcoder.com/acm/contest/19917/B
* 本题使用单点修改线段树可以解决,每个叶子节点处有一个堆,堆的最大值作为叶子处的值
*/

void solve_mmzkw() {
uint32_t n, m, k;
cin >> n >> m >> k;
using monoid = OY::MonoMaxTree<uint32_t>::group;
OY::MaxPqMonoZkwTree<monoid, uint32_t> S(n);
while (m--) {
uint32_t pos, a;
cin >> pos >> a, pos--;
// S[pos] 是一个叶子处的堆
S[pos].push(a);
S.update(pos);
}
while (k--) {
uint32_t l, r, p;
cin >> l >> r >> p, l--, r--;
uint64_t ans = 0;
while (S.query_all() >= p) {
auto pos = S.max_right(l, [&](auto v) { return v < p; }) + 1;
if (pos > r) break;
do ans += S[pos].top(), S[pos].pop();
while (!S[pos].empty() && S[pos].top() >= p);
S.update(pos);
}
cout << ans << endl;
}
}

int main() {
solve_mmzkw();
}
73 changes: 73 additions & 0 deletions TEST/oj/nc_226924.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include "DS/LichaoSegTree.h"
#include "DS/LichaoSegTree_ex.h"
#include "DS/LichaoZkwTree.h"
#include "DS/LichaoZkwTree_ex.h"
#include "IO/FastIO.h"

#include <climits>

/*
[智乃的直线](https://ac.nowcoder.com/acm/problem/226924)
*/
/**
* 上面的链接打不开
* 请换用这个链接 https://ac.nowcoder.com/acm/contest/19917/A
* 本题使用单点修改线段树可以解决,每个叶子节点处有一个堆,堆的最大值作为叶子处的值
*/

void solve_lc() {
uint32_t n, m;
cin >> n >> m;
struct Line {
int m_k, m_b;
Line() = default;
Line(int k, int b) : m_k(k), m_b(b) {}
int64_t calc(int i) const { return int64_t(m_k) * i + m_b; }
};
OY::LCSEG::Tree<Line, std::less<>> S_max(n + 1, {-10000, INT_MIN});
// OY::LCZKW::Tree<Line, std::less<>> S_max(n + 1, {-10000, INT_MIN});
OY::LCSEG::Tree<Line, std::greater<>> S_min(n + 1, {10000, INT_MAX});
// OY::LCZKW::Tree<Line, std::greater<>> S_min(n + 1, {10000, INT_MAX});
while (m--) {
char op;
cin >> op;
if (op == '0') {
int k, b;
cin >> k >> b;
S_max.add(0, n, {k, b});
S_min.add(0, n, {k, b});
} else {
uint32_t x;
cin >> x;
cout << S_max.query(x).calc(x) << ' ' << S_min.query(x).calc(x) << endl;
}
}
}

void solve_lcex() {
uint32_t n, m;
cin >> n >> m;
OY::VectorLichaoSlopeChmaxSegTree_ex<int64_t, INT64_MIN, false, OY::LCSEGEX::BaseLine<int64_t>, uint32_t> S_max(n + 1);
// OY::LichaoSlopeChmaxZkwTree_ex<int64_t, INT64_MIN, false, OY::LCZKWEX::BaseLine<int64_t>> S_max(n + 1);
OY::VectorLichaoSlopeChminSegTree_ex<int64_t, INT64_MAX, false, OY::LCSEGEX::BaseLine<int64_t>, uint32_t> S_min(n + 1);
// OY::LichaoSlopeChminZkwTree_ex<int64_t, INT64_MAX, false, OY::LCZKWEX::BaseLine<int64_t>> S_min(n + 1);
while (m--) {
char op;
cin >> op;
if (op == '0') {
int k, b;
cin >> k >> b;
S_max.add_line(0, n, {k, b});
S_min.add_line(0, n, {k, b});
} else {
uint32_t x;
cin >> x;
cout << S_max.query(x) << ' ' << S_min.query(x) << endl;
}
}
}

int main() {
solve_lc();
// solve_lcex();
}
46 changes: 46 additions & 0 deletions TEST/oj/nc_277952.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "DS/MappedMonoZkwTree.h"
#include "IO/FastIO.h"

/*
[小红的数组操作](https://ac.nowcoder.com/acm/problem/277952)
*/
/**
* 上面的链接打不开
* 请换用这个链接 https://ac.nowcoder.com/acm/contest/88888/F
* 本题使用单点修改线段树可以解决,每个叶子节点处有一个 multiset,multiset 的最小值作为叶子处的值
* multiset 还可以进一步优化为一个懒删除堆
*
* 当然,简便起见,也可以直接用一个子线段树当 multiset
*/

void solve_mmzkw() {
auto read = [](auto...) {
uint32_t x;
cin >> x;
return x;
};
using inner_tree = OY::MonoMinTree<uint32_t>;
using monoid = inner_tree::group;
struct Mapping {
using container_type = inner_tree;
static uint32_t get(const container_type &bucket) { return bucket.size() ? bucket.query_all() : monoid::identity(); }
};
uint32_t n = read();
OY::MMZKW::Tree<monoid, Mapping> S(n);
for (uint32_t i = 0; i != n; i++) S[i].resize(read(), read), S.update(i);
uint32_t q = read();
while (q--) {
char op;
cin >> op;
if (op == '1') {
uint32_t i = read() - 1, j = read() - 1, x = read();
S[i].modify(j, x);
S.update(i);
} else
cout << S.query(0, read() - 1) << endl;
}
}

int main() {
solve_mmzkw();
}
12 changes: 12 additions & 0 deletions TREE/HeavyLightDecomposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ namespace OY {
else if (a != b)
call(info[a].m_dfn + 1, info[b].m_dfn);
}
template <bool LCA, typename Callback>
void do_for_off_path(size_type a, size_type b, Callback &&call) const {
std::pair<size_type, size_type> ranges[32];
size_type cnt = 0;
do_for_path<LCA>(a, b, [&](size_type l, size_type r) { ranges[cnt++] = {l, r}; });
if (!cnt) return;
std::sort(ranges, ranges + cnt);
if (ranges[0].first) call(0, ranges[0].first - 1);
for (size_type i = 1; i != cnt; i++)
if (ranges[i - 1].second + 1 != ranges[i].first) call(ranges[i - 1].second + 1, ranges[i].first - 1);
if (ranges[cnt - 1].second + 1 != m_rooted_tree->vertex_cnt()) call(ranges[cnt - 1].second + 1, m_rooted_tree->vertex_cnt() - 1);
}
template <typename Callback>
void do_for_directed_path(size_type from, size_type to, Callback &&call) const {
auto info = m_info.data();
Expand Down

0 comments on commit f58da5b

Please sign in to comment.