Skip to content

Commit

Permalink
GlobalUnorderedDiscretizer; PARSC2D/PARSM2D/RAPSC2D/RAPSM2D;
Browse files Browse the repository at this point in the history
  • Loading branch information
old-yan committed May 9, 2024
1 parent 9695b28 commit fdeed8e
Show file tree
Hide file tree
Showing 38 changed files with 2,037 additions and 164 deletions.
43 changes: 43 additions & 0 deletions DS/GlobalUnorderedDiscretizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
最后修改:
20240510
测试环境:
gcc11.2,c++11
clang12.0,C++11
msvc14.2,C++14
*/
#ifndef __OY_GLOBALUNORDEREDDISCRETIZER__
#define __OY_GLOBALUNORDEREDDISCRETIZER__

#include "GlobalHashMap.h"

namespace OY {
template <typename Tp, GHASH::size_type BUFFER>
struct GlobalUnorderedDiscretizer {
using hash_table = GHASH::UnorderedMap<Tp, uint32_t, true, BUFFER>;
using node = typename hash_table::node;
hash_table m_hashmap;
GHASH::size_type insert(const Tp &item) {
auto res = m_hashmap.insert(item);
if (res.m_flag) res.m_ptr->m_mapped = m_hashmap.size() - 1;
return res.m_ptr->m_mapped;
}
GHASH::size_type find(const Tp &item) const { return m_hashmap.find(item)->m_mapped; }
template <bool Check = true>
GHASH::size_type rank(const Tp &item) {
if constexpr (Check)
return insert(item);
else
return find(item);
}
GHASH::size_type size() const { return m_hashmap.size(); }
void clear() { m_hashmap.clear(); }
template <typename Callback>
void do_for_each(Callback &&call) {
auto ptr_call = [&](node *p) { call(p->m_key); };
m_hashmap.do_for_each(ptr_call);
}
};
}

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

​ 数据结构:全局无序离散化

​ 练习题目:

1. [U428478 祖孙询问](https://www.luogu.com.cn/problem/U428478)

### 二、模板功能

​ 本模板建立于 `GlobalHashmap` 的基础上。当调用 `rank` 函数返回一个元素的离散化标号。

​ 本模板与 `Discretizer` 模板的差别是,本模板为无序映射,不需要保证小元素对应小标号、大元素对应大标号。因此,并不需要等待全部元素插入完毕之后才能获取标号。

​ 当调用 `rank` 函数时,若模板参数 `Check``true` ,会在获取标号时做检查;而当 `Check``false` ,不做检查。如果确信元素已经在表中,推荐将 `Check` 设为 `false` 。两个版本的 `rank` 函数可以被 `insert` 或者 `find` 代替。


### 三、模板示例

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

OY::GlobalUnorderedDiscretizer<int, 1 << 10> D;
int main() {
cout << "22 -> " << D.insert(22) << endl;
cout << "33 -> " << D.insert(33) << endl;
cout << "11 -> " << D.insert(11) << endl;

// 输出一下存在的元素
cout << "elems: ";
D.do_for_each([](int x) {
cout << x << ' ';
});
cout << endl;
}
```

```
#输出如下
22 -> 0
33 -> 1
11 -> 2
elems: 22 33 11
```

Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ gcc11.2,c++11
clang12.0,C++11
msvc14.2,C++14
*/
#ifndef __OY_OFFLINEPOINTCOUNTER2D__
#define __OY_OFFLINEPOINTCOUNTER2D__
#ifndef __OY_OFFLINEPOINTADDRECTSUMCOUNTER2D__
#define __OY_OFFLINEPOINTADDRECTSUMCOUNTER2D__

#include <algorithm>
#include <cstdint>
#include <vector>

namespace OY {
namespace OFFLINEPC2D {
namespace OFFLINEPARSC2D {
using size_type = uint32_t;
template <typename Tp>
struct SimpleBIT {
Expand Down Expand Up @@ -57,7 +57,7 @@ namespace OY {
m_points.push_back({x, y, w});
}
void add_query(SizeType x_min, SizeType x_max, SizeType y_min, SizeType y_max) { m_queries.push_back({x_min, x_max, y_min, y_max}); }
template <typename SumType = typename std::conditional<std::is_same<WeightType, bool>::value, size_type, WeightType>::type, typename CountTree = SimpleBIT<SumType>>
template <typename SumType = typename std::conditional<is_bool, size_type, WeightType>::type, typename CountTree = SimpleBIT<SumType>>
std::vector<SumType> solve() {
std::sort(m_points.begin(), m_points.end(), [](const point &x, const point &y) { return x.m_y < y.m_y; });
std::vector<SizeType> ys;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### 一、模板类别

​ 数据结构:离线二维矩形区域内点权和查询表
​ 数据结构:离线二维【单点加,矩形区域和查询】表

​ 练习题目:

Expand All @@ -9,7 +9,9 @@

### 二、模板功能

​ 本模板为 `PointCounter2D` 的离线版本,提供了一个 `Solver` ,将区间信息和查询全部塞进去,即可获得查询结果。
​ 本模板为 `PointAddRectSumCounter2D` 的离线版本,适用于先进行加点,再进行查询的问题。

​ 本模板提供了一个 `Solver` ,将区间信息和查询全部塞进去,即可获得查询结果。

​ 类的模板参数有 `typename SizeType` 表示点的坐标类型; `typename WeightType` 表示点权类型。

Expand All @@ -19,11 +21,11 @@
### 三、模板示例

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

void test() {
OY::OFFLINEPC2D::Solver<int, bool> S;
OY::OFFLINEPARSC2D::Solver<int, bool> S;
S.add_point(-1, -1);
S.add_point(-1, 1);
S.add_point(1, -1);
Expand Down
69 changes: 69 additions & 0 deletions DS/OfflinePointAddRectSumMaintainer2D.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
最后修改:
20240506
测试环境:
gcc11.2,c++11
clang12.0,C++11
msvc14.2,C++14
*/
#ifndef __OY_OFFLINEPOINTADDRECTSUMMAINTAINER2D__
#define __OY_OFFLINEPOINTADDRECTSUMMAINTAINER2D__

#include "PointAddRectSumCounter2D.h"

namespace OY {
namespace OFFLINEPARSM2D {
using size_type = uint32_t;
template <typename SizeType, typename WeightType = bool, typename SumType = typename std::conditional<std::is_same<WeightType, bool>::value, size_type, WeightType>::type>
struct Solver {
static constexpr bool is_bool = std::is_same<WeightType, bool>::value;
using weight_type = typename std::conditional<is_bool, size_type, WeightType>::type;
using inner_table = PARSC2D::Table<SizeType, weight_type, SumType, true>;
struct event {
bool m_flag;
union {
struct {
size_type m_id;
weight_type m_w;
};
struct {
SizeType m_x_min, m_x_max, m_y_min, m_y_max;
};
} m_data;
};
inner_table m_table;
size_type m_point_id;
std::vector<event> m_events;
Solver(size_type point_cnt = 0, size_type op_cnt_since_query = 0) : m_table(point_cnt), m_point_id() { m_events.reserve(op_cnt_since_query); }
void add_point(SizeType x, SizeType y, weight_type w = 1) {
if (m_events.empty())
m_table.add_point(x, y, w);
else {
m_table.add_point(x, y, 0);
event e;
e.m_flag = false, e.m_data.m_id = m_point_id, e.m_data.m_w = w;
m_events.push_back(e);
}
m_point_id++;
}
void add_query(SizeType x_min, SizeType x_max, SizeType y_min, SizeType y_max) {
event e;
e.m_flag = true, e.m_data.m_x_min = x_min, e.m_data.m_x_max = x_max, e.m_data.m_y_min = y_min, e.m_data.m_y_max = y_max;
m_events.push_back(e);
}
std::vector<SumType> solve() {
m_table.prepare();
std::vector<SumType> res;
res.reserve(m_events.size());
for (auto &e : m_events)
if (e.m_flag)
res.push_back(m_table.query(e.m_data.m_x_min, e.m_data.m_x_max, e.m_data.m_y_min, e.m_data.m_y_max));
else
m_table.add_point_value(e.m_data.m_id, e.m_data.m_w);
return res;
}
};
};
}

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

​ 数据结构:离线二维【单点加,矩形区域和维护】表

​ 练习题目:

1. [#133. 二维树状数组 1:单点修改,区间查询](https://loj.ac/p/133)
2. [Point Add Rectangle Sum](https://judge.yosupo.jp/problem/point_add_rectangle_sum)(https://github.com/yosupo06/library-checker-problems/issues/519)


### 二、模板功能

​ 本模板为 `PointAddRectSumMaintainer2D` 的离线版本,适用于加点和查询混杂的问题。

​ 本模板提供了一个 `Solver` ,将区间信息和查询全部塞进去,即可获得查询结果。

​ 类的模板参数有 `typename SizeType` 表示点的坐标类型; `typename WeightType` 表示点权类型; `typename SumType` 表示点权和的类型。

### 三、模板示例

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

void test() {
OY::OFFLINEPARSM2D::Solver<int, bool> S;
S.add_query(-1, 1, -1, 1);
S.add_query(0, 1, -1, 1);

S.add_point(-1, -1);
S.add_point(-1, 1);
S.add_point(1, -1);
S.add_point(1, 1);

S.add_query(-1, 1, -1, 1);
S.add_query(0, 1, -1, 1);

auto res = S.solve();

cout << "before add points:\n";
cout << "sum of S{-1<=x<=1, -1<=y<=1}: " << res[0] << endl;
cout << "sum of S{0<=x<=1, -1<=y<=1}: " << res[1] << endl;

cout << "after add points:\n";
cout << "sum of S{-1<=x<=1, -1<=y<=1}: " << res[2] << endl;
cout << "sum of S{0<=x<=1, -1<=y<=1}: " << res[3] << endl;
}

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

```
#输出如下
before add points:
sum of S{-1<=x<=1, -1<=y<=1}: 0
sum of S{0<=x<=1, -1<=y<=1}: 0
after add points:
sum of S{-1<=x<=1, -1<=y<=1}: 4
sum of S{0<=x<=1, -1<=y<=1}: 2
```

Loading

0 comments on commit fdeed8e

Please sign in to comment.