Skip to content

Commit

Permalink
adj-diff-tree use monoid; add slide-window;
Browse files Browse the repository at this point in the history
  • Loading branch information
old-yan committed Oct 13, 2024
1 parent be36edc commit 5764cab
Show file tree
Hide file tree
Showing 16 changed files with 385 additions and 147 deletions.
28 changes: 14 additions & 14 deletions DS/AdjDiff.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ namespace OY {
Table(size_type length, InitMapping mapping) { resize(length, mapping); }
template <typename Iterator>
Table(Iterator first, Iterator last) { reset(first, last); }
void resize(size_type length) { m_v.assign(length, group::identity()), m_state = TableState::TABLE_ANY; }
void resize(size_type length) { m_v.assign(length, group::identity()), m_state = TABLE_ANY; }
template <typename InitMapping>
void resize(size_type length, InitMapping mapping) {
m_v.resize(length);
for (size_type i = 0; i != length; i++) m_v[i] = mapping(i);
m_state = TableState::TABLE_VALUE;
m_state = TABLE_VALUE;
}
template <typename Iterator>
void reset(Iterator first, Iterator last) {
Expand All @@ -92,22 +92,22 @@ namespace OY {
value_type query(size_type left, size_type right) const { return _auto_to_presum(), (left - 1 == right ? group::identity() : group::op(_get(right), group::inverse(_get(left - 1)))); }
value_type query_all() const { return _auto_to_presum(), _get(size() - 1); }
void switch_to_difference() const {
if (m_state == TableState::TABLE_DIFFERENCE) return;
if (m_state == TableState::TABLE_ANY) return (void)(m_state = TableState::TABLE_DIFFERENCE);
if (m_state == TableState::TABLE_PRESUM) _adjacent_difference();
if (m_state == TableState::TABLE_VALUE) _adjacent_difference();
if (m_state == TABLE_DIFFERENCE) return;
if (m_state == TABLE_ANY) return (void)(m_state = TABLE_DIFFERENCE);
if (m_state == TABLE_PRESUM) _adjacent_difference();
if (m_state == TABLE_VALUE) _adjacent_difference();
}
void switch_to_value() const {
if (m_state == TableState::TABLE_VALUE) return;
if (m_state == TableState::TABLE_ANY) return (void)(m_state = TableState::TABLE_VALUE);
if (m_state == TableState::TABLE_DIFFERENCE) _partial_sum();
if (m_state == TableState::TABLE_PRESUM) _adjacent_difference();
if (m_state == TABLE_VALUE) return;
if (m_state == TABLE_ANY) return (void)(m_state = TABLE_VALUE);
if (m_state == TABLE_DIFFERENCE) _partial_sum();
if (m_state == TABLE_PRESUM) _adjacent_difference();
}
void switch_to_presum() const {
if (m_state == TableState::TABLE_PRESUM) return;
if (m_state == TableState::TABLE_ANY) return (void)(m_state = TableState::TABLE_PRESUM);
if (m_state == TableState::TABLE_DIFFERENCE) _partial_sum();
if (m_state == TableState::TABLE_VALUE) _partial_sum();
if (m_state == TABLE_PRESUM) return;
if (m_state == TABLE_ANY) return (void)(m_state = TABLE_PRESUM);
if (m_state == TABLE_DIFFERENCE) _partial_sum();
if (m_state == TABLE_VALUE) _partial_sum();
}
};
template <typename Ostream, typename CommutativeGroup, bool AutoSwitch>
Expand Down
28 changes: 14 additions & 14 deletions DS/AdjDiff2D.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ namespace OY {
void resize(size_type row, size_type column) {
if (!(m_row = row) || !(m_column = column)) return;
m_sum.assign(m_row * m_column, group::identity());
m_state = TableState::TABLE_ANY;
m_state = TABLE_ANY;
}
template <typename InitMapping>
void resize(size_type row, size_type column, InitMapping mapping) {
if (!(m_row = row) || !(m_column = column)) return;
m_sum.resize(m_row * m_column);
for (size_type i = 0, k = 0; i != m_row; i++)
for (size_type j = 0; j != m_column; j++) m_sum[k++] = mapping(i, j);
m_state = TableState::TABLE_VALUE;
m_state = TABLE_VALUE;
}
size_type row() const { return m_row; }
size_type column() const { return m_column; }
Expand All @@ -100,22 +100,22 @@ namespace OY {
value_type query(size_type r1, size_type r2, size_type c1, size_type c2) const { return _auto_to_presum(), _get(r1 - 1, c1 - 1) - _get(r1 - 1, c2) - _get(r2, c1 - 1) + _get(r2, c2); }
value_type query_all() const { return _auto_to_presum(), _get(m_row - 1, m_column - 1); }
void switch_to_difference() const {
if (m_state == TableState::TABLE_DIFFERENCE) return;
if (m_state == TableState::TABLE_ANY) return (void)(m_state = TableState::TABLE_DIFFERENCE);
if (m_state == TableState::TABLE_PRESUM) _adjacent_difference();
if (m_state == TableState::TABLE_VALUE) _adjacent_difference();
if (m_state == TABLE_DIFFERENCE) return;
if (m_state == TABLE_ANY) return (void)(m_state = TABLE_DIFFERENCE);
if (m_state == TABLE_PRESUM) _adjacent_difference();
if (m_state == TABLE_VALUE) _adjacent_difference();
}
void switch_to_value() const {
if (m_state == TableState::TABLE_VALUE) return;
if (m_state == TableState::TABLE_ANY) return (void)(m_state = TableState::TABLE_VALUE);
if (m_state == TableState::TABLE_DIFFERENCE) _partial_sum();
if (m_state == TableState::TABLE_PRESUM) _adjacent_difference();
if (m_state == TABLE_VALUE) return;
if (m_state == TABLE_ANY) return (void)(m_state = TABLE_VALUE);
if (m_state == TABLE_DIFFERENCE) _partial_sum();
if (m_state == TABLE_PRESUM) _adjacent_difference();
}
void switch_to_presum() const {
if (m_state == TableState::TABLE_PRESUM) return;
if (m_state == TableState::TABLE_ANY) return (void)(m_state = TableState::TABLE_PRESUM);
if (m_state == TableState::TABLE_DIFFERENCE) _partial_sum();
if (m_state == TableState::TABLE_VALUE) _partial_sum();
if (m_state == TABLE_PRESUM) return;
if (m_state == TABLE_ANY) return (void)(m_state = TABLE_PRESUM);
if (m_state == TABLE_DIFFERENCE) _partial_sum();
if (m_state == TABLE_VALUE) _partial_sum();
}
};
template <typename Ostream, typename CommutativeGroup, bool AutoSwitch>
Expand Down
26 changes: 13 additions & 13 deletions DS/MonoAVL.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
​ 练习题目:



1. [P1503 鬼子进村](https://www.luogu.com.cn/problem/P1503)
2. [P1886 滑动窗口 /【模板】单调队列](https://www.luogu.com.cn/problem/P1886)
3. [P3369 【模板】普通平衡树](https://www.luogu.com.cn/problem/P3369)
4. [P3391 【模板】文艺平衡树](https://www.luogu.com.cn/problem/P3391)
5. [P4036 [JSOI2008] 火星人](https://www.luogu.com.cn/problem/P4036)
6. [P4774 [NOI2018] 屠龙勇士](https://www.luogu.com.cn/problem/P4774)
7. [P6136 【模板】普通平衡树(数据加强版)](https://www.luogu.com.cn/problem/P6136)
8. [U361730 【模板】完全体·堆](https://www.luogu.com.cn/problem/U361730)
9. [翻转排序](https://ac.nowcoder.com/acm/problem/275173)
10. [旅途的终点](https://ac.nowcoder.com/acm/problem/275989)
11. [正义从不打背身](https://ac.nowcoder.com/acm/problem/277862)
12. [Range Reverse Range Sum](https://judge.yosupo.jp/problem/range_reverse_range_sum)(https://github.com/yosupo06/library-checker-problems/issues/538)
1. [3321. 计算子数组的 x-sum II](https://leetcode.cn/problems/find-x-sum-of-all-k-long-subarrays-ii)
2. [P1503 鬼子进村](https://www.luogu.com.cn/problem/P1503)
3. [P1886 滑动窗口 /【模板】单调队列](https://www.luogu.com.cn/problem/P1886)
4. [P3369 【模板】普通平衡树](https://www.luogu.com.cn/problem/P3369)
5. [P3391 【模板】文艺平衡树](https://www.luogu.com.cn/problem/P3391)
6. [P4036 [JSOI2008] 火星人](https://www.luogu.com.cn/problem/P4036)
7. [P4774 [NOI2018] 屠龙勇士](https://www.luogu.com.cn/problem/P4774)
8. [P6136 【模板】普通平衡树(数据加强版)](https://www.luogu.com.cn/problem/P6136)
9. [U361730 【模板】完全体·堆](https://www.luogu.com.cn/problem/U361730)
10. [翻转排序](https://ac.nowcoder.com/acm/problem/275173)
11. [旅途的终点](https://ac.nowcoder.com/acm/problem/275989)
12. [正义从不打背身](https://ac.nowcoder.com/acm/problem/277862)
13. [Range Reverse Range Sum](https://judge.yosupo.jp/problem/range_reverse_range_sum)(https://github.com/yosupo06/library-checker-problems/issues/538)


### 二、模板功能
Expand Down
25 changes: 13 additions & 12 deletions DS/MonoSplay.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@

​ 练习题目:

1. [P1503 鬼子进村](https://www.luogu.com.cn/problem/P1503)
2. [P1886 滑动窗口 /【模板】单调队列](https://www.luogu.com.cn/problem/P1886)
3. [P3369 【模板】普通平衡树](https://www.luogu.com.cn/problem/P3369)
4. [P3391 【模板】文艺平衡树](https://www.luogu.com.cn/problem/P3391)
5. [P4036 [JSOI2008] 火星人](https://www.luogu.com.cn/problem/P4036)
6. [P4774 [NOI2018] 屠龙勇士](https://www.luogu.com.cn/problem/P4774)
7. [P6136 【模板】普通平衡树(数据加强版)](https://www.luogu.com.cn/problem/P6136)
8. [U361730 【模板】完全体·堆](https://www.luogu.com.cn/problem/U361730)
9. [翻转排序](https://ac.nowcoder.com/acm/problem/275173)
10. [旅途的终点](https://ac.nowcoder.com/acm/problem/275989)
11. [正义从不打背身](https://ac.nowcoder.com/acm/problem/277862)
12. [Range Reverse Range Sum](https://judge.yosupo.jp/problem/range_reverse_range_sum)(https://github.com/yosupo06/library-checker-problems/issues/538)
1. [3321. 计算子数组的 x-sum II](https://leetcode.cn/problems/find-x-sum-of-all-k-long-subarrays-ii)
2. [P1503 鬼子进村](https://www.luogu.com.cn/problem/P1503)
3. [P1886 滑动窗口 /【模板】单调队列](https://www.luogu.com.cn/problem/P1886)
4. [P3369 【模板】普通平衡树](https://www.luogu.com.cn/problem/P3369)
5. [P3391 【模板】文艺平衡树](https://www.luogu.com.cn/problem/P3391)
6. [P4036 [JSOI2008] 火星人](https://www.luogu.com.cn/problem/P4036)
7. [P4774 [NOI2018] 屠龙勇士](https://www.luogu.com.cn/problem/P4774)
8. [P6136 【模板】普通平衡树(数据加强版)](https://www.luogu.com.cn/problem/P6136)
9. [U361730 【模板】完全体·堆](https://www.luogu.com.cn/problem/U361730)
10. [翻转排序](https://ac.nowcoder.com/acm/problem/275173)
11. [旅途的终点](https://ac.nowcoder.com/acm/problem/275989)
12. [正义从不打背身](https://ac.nowcoder.com/acm/problem/277862)
13. [Range Reverse Range Sum](https://judge.yosupo.jp/problem/range_reverse_range_sum)(https://github.com/yosupo06/library-checker-problems/issues/538)


### 二、模板功能
Expand Down
34 changes: 34 additions & 0 deletions MISC/SlideWindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
最后修改:
20241013
测试环境:
gcc11.2,c++14
clang12.0,C++14
msvc14.2,C++14
*/
#ifndef __OY_SLIDEWINDOW__
#define __OY_SLIDEWINDOW__

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

namespace OY {
namespace WINDOW {
using size_type = uint32_t;
template <typename Callback, typename ShortenLeft, typename LengthenRight>
void solve(size_type length, size_type window_len, Callback &&call, ShortenLeft &&left_call, LengthenRight &&right_call) {
size_type l = 0, r = 0;
while (r != window_len) right_call(r++);
call(l, r - 1);
while (r != length) {
left_call(l++);
right_call(r++);
call(l, r - 1);
}
}
}
}

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

​ 数据结构:滑动窗口。

​ 练习题目:

1. [3321. 计算子数组的 x-sum II](https://leetcode.cn/problems/find-x-sum-of-all-k-long-subarrays-ii)


### 二、模板功能

​ 本模板提供一个滑动窗口模板。

​ 滑动窗口问题中,需要知道区间总长度、窗口长度、窗口左端收缩的回调函数、窗口右端收缩的回调函数、窗口就绪的回调函数。只要传递这些参数,本模板即可自动运行。

### 三、模板示例

```c++
#include "IO/FastIO.h"
#include "MISC/SlideWindow.h"

#include <map>
void test() {
// 窗口数颜色
cout << "count color count:\n";
int a[] = {4, 7, 5, 1, 8, 1, 4, 4, 1};

int n = 9;
int window_len = 4;
std::map<int, int> mp;
auto call = [&](int l, int r) {
cout << "color count of [";
for (int i = l; i <= r; i++) cout << a[i] << " ]"[i == r];
cout << " = " << mp.size() << endl;
};
auto left_call = [&](int i) {
auto &cnt = mp[a[i]];
if (!--cnt) mp.erase(a[i]);
};
auto right_call = [&](int i) {
auto &cnt = mp[a[i]];
++cnt;
};
OY::WINDOW::solve(n, window_len, call, left_call, right_call);
}

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

```
#输出如下
count color count:
color count of [4 7 5 1] = 4
color count of [7 5 1 8] = 4
color count of [5 1 8 1] = 3
color count of [1 8 1 4] = 3
color count of [8 1 4 4] = 3
color count of [1 4 4 1] = 2
```

4 changes: 2 additions & 2 deletions TEST/local/AdjDiffTree_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void Ad_manual() {
cout << T << endl;

// 假定每个点的初值都是编号 * 1000
OY::AdjDiffTree::Table<int, decltype(T), false> Ad(&T, [&](int i) {
OY::AdjSumTreeTable<int, decltype(T), false> Ad(&T, [&](int i) {
return i * 1000;
});
cout << Ad << endl;
Expand Down Expand Up @@ -57,7 +57,7 @@ void Ad_auto() {
T.set_root(0);
cout << T << endl;

OY::AdjDiffTree::Table<int, decltype(T), true> Ad(&T, [&](int i) {
OY::AdjSumTreeTable<int, decltype(T), true> Ad(&T, [&](int i) {
return i * 1000;
});
cout << Ad << endl;
Expand Down
42 changes: 42 additions & 0 deletions TEST/local/SlideWindow_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "IO/FastIO.h"
#include "MISC/SlideWindow.h"

#include <map>
void test() {
// 窗口数颜色
cout << "count color count:\n";
int a[] = {4, 7, 5, 1, 8, 1, 4, 4, 1};

int n = 9;
int window_len = 4;
std::map<int, int> mp;
auto call = [&](int l, int r) {
cout << "color count of [";
for (int i = l; i <= r; i++) cout << a[i] << " ]"[i == r];
cout << " = " << mp.size() << endl;
};
auto left_call = [&](int i) {
auto &cnt = mp[a[i]];
if (!--cnt) mp.erase(a[i]);
};
auto right_call = [&](int i) {
auto &cnt = mp[a[i]];
++cnt;
};
OY::WINDOW::solve(n, window_len, call, left_call, right_call);
}

int main() {
test();
}
/*
#输出如下
count color count:
color count of [4 7 5 1] = 4
color count of [7 5 1 8] = 4
color count of [5 1 8 1] = 3
color count of [1 8 1 4] = 3
color count of [8 1 4 4] = 3
color count of [1 4 4 1] = 2
*/
67 changes: 67 additions & 0 deletions TEST/oj/lc_3321.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include "DS/MonoAVL.h"
#include "DS/MonoSplay.h"
#include "IO/LeetcodeIO.h"
#include "MISC/SlideWindow.h"
using namespace std;

/*
[3321. 计算子数组的 x-sum II](https://leetcode.cn/problems/find-x-sum-of-all-k-long-subarrays-ii)
*/
/**
* 滑动窗口模板,平衡树模板
*/

class Solution {
public:
vector<long long> findXSum(vector<int> &nums, int k, int x) {
// 本平衡树维护两个属性的和
// 属性一是频率
// 属性二是键和频率的乘积
struct Monoid {
using value_type = pair<int, long long>;
static value_type op(value_type x, value_type y) { return {x.first + y.first, x.second + y.second}; }
static value_type identity() { return {0, 0}; }
};
using Tree = OY::MONOAVL::Tree<Monoid, false>;
// using Tree = OY::MONOSPLAY::Tree<Monoid, false>;
Tree S;
// mp 维护频率
unordered_map<int, int> mp;
vector<long long> ans;
// 给固定大小的滑动窗口传递回调函数
// 对已就绪的窗口调用的回调
auto call = [&](int l, int r) {
if (S.size() < x)
ans.push_back(S.query_all().second);
else
ans.push_back(S.query(S.size() - x, S.size() - 1).second);
};
// 左端点右移的回调
auto left_call = [&](int i) {
auto &cnt = mp[nums[i]];
if (cnt) S.erase_by_comparator({cnt, 1ll * nums[i] * cnt});
--cnt;
if (cnt) S.insert_by_comparator({cnt, 1ll * nums[i] * cnt});
};
// 右端点右移的回调
auto right_call = [&](int i) {
auto &cnt = mp[nums[i]];
if (cnt) S.erase_by_comparator({cnt, 1ll * nums[i] * cnt});
++cnt;
if (cnt) S.insert_by_comparator({cnt, 1ll * nums[i] * cnt});
};
OY::WINDOW::solve(nums.size(), k, call, left_call, right_call);
return ans;
}
};

#ifdef OY_LOCAL
int main() {
REGISTER_CONSTRUCTOR_SOLUTION;
REGISTER_MEMBERFUNCTION_SOLUTION(findXSum);
while (true) {
executor.constructSolution();
executor.executeSolution();
}
}
#endif
Loading

0 comments on commit 5764cab

Please sign in to comment.