-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
old-yan
committed
Feb 9, 2025
1 parent
edf99bf
commit f58da5b
Showing
13 changed files
with
326 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters