From 3625e1051dff555a5554e57ae6f04aa14f334de3 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Tue, 11 Nov 2025 20:47:40 +0800 Subject: [PATCH 01/25] add code --- heap.cpp | 70 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/heap.cpp b/heap.cpp index 53d517d..d14d1ff 100644 --- a/heap.cpp +++ b/heap.cpp @@ -1,35 +1,51 @@ #include using namespace std; -class Solution { -public: - vector sortArray(vector& nums) { - for (int i = nums.size() - 1; i >= 0; --i) { - heapify(nums, i, nums.size()); - } - for (int i = nums.size() - 1; i >= 1; --i) { - swap(nums[0], nums[i]); - heapify(nums, 0, i); - } - return nums; +// 最小堆 +struct heap +{ + vector a; + void push(int x) + { + a.push_back(x); + up(a.size() - 1); + } + int top() + { + return a.front(); + } + void pop() + { + swap(a.front(), a.back()); + a.pop_back(); + down(0); + } + int fa(int i) + { + return (i - 1) / 2; + } + int ls(int i) + { + return i * 2 + 1; + } + int rs(int i) + { + return i * 2 + 2; } - void heapInsert(vector& nums, int i) { - while (nums[i] > nums[(i - 1) / 2]) { - swap(nums[i], nums[(i - 1) / 2]); - i = (i - 1) / 2; + void up(int i) + { + while (i && a[i] < a[fa(i)]) + { + swap(a[i], a[fa(i)]); + i = fa(i); } } - void heapify(vector& nums, int i, int n) { - int best; - while (i * 2 + 1 < n) { - best = (i * 2 + 2 < n && nums[i * 2 + 2] > nums[i * 2 + 1]) - ? i * 2 + 2 - : i * 2 + 1; - best = nums[best] > nums[i] ? best : i; - if (best == i) { - break; - } - swap(nums[i], nums[best]); - i = best; + void down(int i) + { + while (ls(i) < a.size() && (a[i] > a[ls(i)] || rs(i) < a.size() && a[i] > a[rs(i)])) + { + int j = rs(i) < a.size() && a[rs(i)] < a[ls(i)] ? rs(i) : ls(i); + swap(a[i], a[j]); + i = j; } } }; \ No newline at end of file From d2a4cea5af1d7adf8dee17c15b75c27402479900 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Tue, 11 Nov 2025 23:32:14 +0800 Subject: [PATCH 02/25] add code --- lca_tarjan.cpp | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 lca_tarjan.cpp diff --git a/lca_tarjan.cpp b/lca_tarjan.cpp new file mode 100644 index 0000000..0012941 --- /dev/null +++ b/lca_tarjan.cpp @@ -0,0 +1,83 @@ +// https://www.luogu.com.cn/problem/P3379 +#include +using namespace std; +using ll = long long; +using pii = pair; +#define rep(i, j, k) for (int i = (j); i <= (k); ++i) +#define rrep(i, j, k) for (int i = (j); i >= (k); --i) +const int INF = 0x3f3f3f3f; +const int MOD = 1e9 + 7; +vector> g; +vector>> query; +vector vis, ans, pre; +int fin(int u) +{ + return pre[u] = pre[u] == u ? u : fin(pre[u]); +} +void uni(int u, int v) +{ + u = fin(u); + v = fin(v); + pre[u] = v; +} +void tarjan(int u) +{ + vis[u] = 1; + for (auto v : g[u]) + { + if (!vis[v]) + { + tarjan(v); + pre[v] = u; + } + } + for (auto [v, i] : query[u]) + { + if (vis[v]) + { + ans[i] = fin(v); + } + } +} +void solve() +{ + int n, m, s; + cin >> n >> m >> s; + g.resize(n + 1); + query.resize(n + 1); + vis.resize(n + 1); + pre.resize(n + 1); + ans.resize(n + 1); + for (int i = 1; i <= n; ++i) + pre[i] = i; + for (int i = 1; i < n; ++i) + { + int u, v; + cin >> u >> v; + g[u].push_back(v); + g[v].push_back(u); + } + for (int i = 1; i <= m; ++i) + { + int u, v; + cin >> u >> v; + query[u].push_back({v, i}); + query[v].push_back({u, i}); + } + tarjan(s); + for (int i = 1; i <= m; ++i) + cout << ans[i] << "\n"; +} +int main() +{ + ios::sync_with_stdio(0); + cin.tie(0); + cout.tie(0); + int t = 1; + // cin >> t; + while (t--) + { + solve(); + } + return 0; +} \ No newline at end of file From 93e91df0cbba8ec0456017bd248836f9f6ca5d2a Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Tue, 11 Nov 2025 23:35:51 +0800 Subject: [PATCH 03/25] modify code --- Gost_Tree.cpp => scapegoat_tree.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Gost_Tree.cpp => scapegoat_tree.cpp (100%) diff --git a/Gost_Tree.cpp b/scapegoat_tree.cpp similarity index 100% rename from Gost_Tree.cpp rename to scapegoat_tree.cpp From 57b0c755efa75128dea30c2dcdfc0d7d4fc2a08e Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Fri, 14 Nov 2025 19:00:41 +0800 Subject: [PATCH 04/25] add code --- shell_sort.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 shell_sort.cpp diff --git a/shell_sort.cpp b/shell_sort.cpp new file mode 100644 index 0000000..f96aebd --- /dev/null +++ b/shell_sort.cpp @@ -0,0 +1,19 @@ +#include +using namespace std; +void shell_sort(vector &arr) +{ + int n = arr.size(); + for (int gap = n / 2; gap > 0; gap /= 2) + { + for (int i = gap; i < n; i++) + { + int temp = arr[i]; + int j; + for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) + { + arr[j] = arr[j - gap]; + } + arr[j] = temp; + } + } +} \ No newline at end of file From 933875d2bb499f3fa92fce83d06bbd90d12bd0f9 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Fri, 14 Nov 2025 19:56:25 +0800 Subject: [PATCH 05/25] add code --- hld.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 hld.cpp diff --git a/hld.cpp b/hld.cpp new file mode 100644 index 0000000..d4b856e --- /dev/null +++ b/hld.cpp @@ -0,0 +1,47 @@ +// 树链剖分 +#include +using namespace std; +struct hld +{ + vector> g; + vector fa, dep, son, sz, top; + hld(int n) : g(n), fa(n), dep(n), son(n), sz(n), top(n) {}; + void dfs1(int u, int f) + { + fa[u] = f; + dep[u] = dep[f] + 1; + sz[u] = 1; + for (auto v : g[u]) + { + if (v == f) + continue; + dfs1(v, u); + sz[u] += sz[v]; + if (sz[son[u]] < sz[v]) + son[u] = v; + } + } + void dfs2(int u, int t) + { + top[u] = t; + if (!son[u]) + return; + dfs2(son[u], t); + for (auto v : g[u]) + { + if (v == fa[u] || v == son[u]) + continue; + dfs2(v, v); + } + } + int lca(int u, int v) + { + while (top[u] != top[v]) + { + if (dep[top[u]] < dep[top[v]]) + swap(u, v); + u = fa[top[u]]; + } + return dep[u] < dep[v] ? u : v; + } +}; \ No newline at end of file From a191ac60880b6aa105901eebbf9fd09508cb7593 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Tue, 18 Nov 2025 23:46:57 +0800 Subject: [PATCH 06/25] add code --- bridge.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 bridge.cpp diff --git a/bridge.cpp b/bridge.cpp new file mode 100644 index 0000000..a765c3b --- /dev/null +++ b/bridge.cpp @@ -0,0 +1,55 @@ +#include +using namespace std; +// 图的邻接表 +vector> g; +// 存储割边 +vector> e; +vector dfn, low; +int tot; +// tarjan算法求割边(桥) +void tarjan(int u, int fa) +{ + dfn[u] = low[u] = tot++; + // 是否访问过连向父亲的边 + bool fa_edge = false; + for (auto v : g[u]) + { + if (dfn[v] == -1) + { + tarjan(v, u); + low[u] = min(low[u], low[v]); + if (low[v] > dfn[u]) + // 发现割边 + e.push_back({min(u, v), max(u, v)}); + } + // 若目标节点不是父亲或访问到连向父亲的重边 + else if (v != fa || fa_edge) + low[u] = min(low[u], dfn[v]); + else + fa_edge = true; + } +} +int main() +{ + int n, m; + cin >> n >> m; + g.resize(n); + dfn.resize(n, -1); + low.resize(n, -1); + for (int i = 0; i < m; ++i) + { + int u, v; + cin >> u >> v; + u--; + v--; + g[u].push_back(v); + g[v].push_back(u); + } + for (int i = 0; i < n; ++i) + if (dfn[i] == -1) + tarjan(i, -1); + sort(e.begin(), e.end()); + for (auto [u, v] : e) + cout << u + 1 << " " << v + 1 << "\n"; + return 0; +} \ No newline at end of file From 6bdf8197d9353e4b058d19e47e74ad98787714de Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Wed, 19 Nov 2025 01:28:53 +0800 Subject: [PATCH 07/25] modify code --- bridge.cpp | 24 ------------------------ cut_node.cpp | 35 +++++++++++++++++++++++++++++++++++ scc.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ shell_sort.cpp | 3 +++ 4 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 cut_node.cpp create mode 100644 scc.cpp diff --git a/bridge.cpp b/bridge.cpp index a765c3b..c4377bf 100644 --- a/bridge.cpp +++ b/bridge.cpp @@ -28,28 +28,4 @@ void tarjan(int u, int fa) else fa_edge = true; } -} -int main() -{ - int n, m; - cin >> n >> m; - g.resize(n); - dfn.resize(n, -1); - low.resize(n, -1); - for (int i = 0; i < m; ++i) - { - int u, v; - cin >> u >> v; - u--; - v--; - g[u].push_back(v); - g[v].push_back(u); - } - for (int i = 0; i < n; ++i) - if (dfn[i] == -1) - tarjan(i, -1); - sort(e.begin(), e.end()); - for (auto [u, v] : e) - cout << u + 1 << " " << v + 1 << "\n"; - return 0; } \ No newline at end of file diff --git a/cut_node.cpp b/cut_node.cpp new file mode 100644 index 0000000..ee8f0f4 --- /dev/null +++ b/cut_node.cpp @@ -0,0 +1,35 @@ +#include +using namespace std; +// 图的邻接表 +vector> g; +vector dfn, low; +// 是否是割点 +vector cut; +int tot, rt; +// tarjan算法求割点 +void tarjan(int u) +{ + dfn[u] = low[u] = tot++; + int son = 0; + for (int v : g[u]) + { + if (dfn[v] == -1) + { + tarjan(v); + low[u] = min(low[u], low[v]); + // 邻居要满足下面条件 + if (low[v] >= dfn[u]) + { + son++; + // 当节点不是根或满足条件的邻居多于1个 + // 则该节点是割点 + if (u != rt || son > 1) + cut[u] = true; + } + } + else + { + low[u] = min(low[u], dfn[v]); + } + } +} \ No newline at end of file diff --git a/scc.cpp b/scc.cpp new file mode 100644 index 0000000..c8d052c --- /dev/null +++ b/scc.cpp @@ -0,0 +1,42 @@ +#include +using namespace std; +// 邻接表, 强连通分量集合 +vector> g, sccs; +vector dfn, low; +// 是否在栈中, 即是否在搜索路径中 +vector instk; +// 路径上的点压栈 +stack stk; +// 当前访问时间戳 +int tot; +// tarjan算法求强连通分量 +void tarjan(int u) +{ + dfn[u] = low[u] = tot++; + stk.push(u); + instk[u] = true; + for (auto v : g[u]) + { + if (dfn[v] == -1) + { + tarjan(v); + low[u] = min(low[u], low[v]); + } + else if (instk[v]) + { + low[u] = min(low[u], dfn[v]); + } + } + if (dfn[u] != low[u]) + return; + // 该点是强连通分量的根 + sccs.push_back({}); + int v; + do + { + v = stk.top(); + stk.pop(); + instk[v] = false; + sccs.back().push_back(v); + } while (v != u); +} \ No newline at end of file diff --git a/shell_sort.cpp b/shell_sort.cpp index f96aebd..560c180 100644 --- a/shell_sort.cpp +++ b/shell_sort.cpp @@ -1,10 +1,13 @@ #include using namespace std; +// 希尔排序 void shell_sort(vector &arr) { int n = arr.size(); + // 枚举步长并分组 for (int gap = n / 2; gap > 0; gap /= 2) { + // 对每组插入排序 for (int i = gap; i < n; i++) { int temp = arr[i]; From b1db55f89541fa523ed2e088a72e4fa6cc75ff12 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Wed, 19 Nov 2025 16:07:51 +0800 Subject: [PATCH 08/25] modify filename --- AVL_Tree.cpp => "AVL\346\240\221.cpp" | 0 lca_tarjan.cpp => Tarjan_LCA.cpp | 0 cut_node.cpp => "\345\211\262\347\202\271.cpp" | 0 heap.cpp => "\345\240\206.cpp" | 0 ....cpp => "\345\270\214\345\260\224\346\216\222\345\272\217.cpp" | 0 ...5\274\272\350\277\236\351\200\232\345\210\206\351\207\217.cpp" | 0 ....cpp => "\346\233\277\347\275\252\347\276\212\346\240\221.cpp" | 0 ....cpp => "\346\240\221\344\270\212\350\203\214\345\214\205.cpp" | 0 hld.cpp => "\346\240\221\351\223\276\345\211\226\345\210\206.cpp" | 0 bridge.cpp => "\346\241\245.cpp" | 0 backpack.cpp => "\350\203\214\345\214\205.cpp" | 0 jump_list.cpp => "\350\267\263\350\241\250.cpp" | 0 ...p => "\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" | 0 ...5\272\246\345\215\201\350\277\233\345\210\266\346\225\260.cpp" | 0 14 files changed, 0 insertions(+), 0 deletions(-) rename AVL_Tree.cpp => "AVL\346\240\221.cpp" (100%) rename lca_tarjan.cpp => Tarjan_LCA.cpp (100%) rename cut_node.cpp => "\345\211\262\347\202\271.cpp" (100%) rename heap.cpp => "\345\240\206.cpp" (100%) rename shell_sort.cpp => "\345\270\214\345\260\224\346\216\222\345\272\217.cpp" (100%) rename scc.cpp => "\345\274\272\350\277\236\351\200\232\345\210\206\351\207\217.cpp" (100%) rename scapegoat_tree.cpp => "\346\233\277\347\275\252\347\276\212\346\240\221.cpp" (100%) rename backpack_tree.cpp => "\346\240\221\344\270\212\350\203\214\345\214\205.cpp" (100%) rename hld.cpp => "\346\240\221\351\223\276\345\211\226\345\210\206.cpp" (100%) rename bridge.cpp => "\346\241\245.cpp" (100%) rename backpack.cpp => "\350\203\214\345\214\205.cpp" (100%) rename jump_list.cpp => "\350\267\263\350\241\250.cpp" (100%) rename dfs_stack.cpp => "\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" (100%) rename big_decimal.cpp => "\351\253\230\347\262\276\345\272\246\345\215\201\350\277\233\345\210\266\346\225\260.cpp" (100%) diff --git a/AVL_Tree.cpp "b/AVL\346\240\221.cpp" similarity index 100% rename from AVL_Tree.cpp rename to "AVL\346\240\221.cpp" diff --git a/lca_tarjan.cpp b/Tarjan_LCA.cpp similarity index 100% rename from lca_tarjan.cpp rename to Tarjan_LCA.cpp diff --git a/cut_node.cpp "b/\345\211\262\347\202\271.cpp" similarity index 100% rename from cut_node.cpp rename to "\345\211\262\347\202\271.cpp" diff --git a/heap.cpp "b/\345\240\206.cpp" similarity index 100% rename from heap.cpp rename to "\345\240\206.cpp" diff --git a/shell_sort.cpp "b/\345\270\214\345\260\224\346\216\222\345\272\217.cpp" similarity index 100% rename from shell_sort.cpp rename to "\345\270\214\345\260\224\346\216\222\345\272\217.cpp" diff --git a/scc.cpp "b/\345\274\272\350\277\236\351\200\232\345\210\206\351\207\217.cpp" similarity index 100% rename from scc.cpp rename to "\345\274\272\350\277\236\351\200\232\345\210\206\351\207\217.cpp" diff --git a/scapegoat_tree.cpp "b/\346\233\277\347\275\252\347\276\212\346\240\221.cpp" similarity index 100% rename from scapegoat_tree.cpp rename to "\346\233\277\347\275\252\347\276\212\346\240\221.cpp" diff --git a/backpack_tree.cpp "b/\346\240\221\344\270\212\350\203\214\345\214\205.cpp" similarity index 100% rename from backpack_tree.cpp rename to "\346\240\221\344\270\212\350\203\214\345\214\205.cpp" diff --git a/hld.cpp "b/\346\240\221\351\223\276\345\211\226\345\210\206.cpp" similarity index 100% rename from hld.cpp rename to "\346\240\221\351\223\276\345\211\226\345\210\206.cpp" diff --git a/bridge.cpp "b/\346\241\245.cpp" similarity index 100% rename from bridge.cpp rename to "\346\241\245.cpp" diff --git a/backpack.cpp "b/\350\203\214\345\214\205.cpp" similarity index 100% rename from backpack.cpp rename to "\350\203\214\345\214\205.cpp" diff --git a/jump_list.cpp "b/\350\267\263\350\241\250.cpp" similarity index 100% rename from jump_list.cpp rename to "\350\267\263\350\241\250.cpp" diff --git a/dfs_stack.cpp "b/\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" similarity index 100% rename from dfs_stack.cpp rename to "\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" diff --git a/big_decimal.cpp "b/\351\253\230\347\262\276\345\272\246\345\215\201\350\277\233\345\210\266\346\225\260.cpp" similarity index 100% rename from big_decimal.cpp rename to "\351\253\230\347\262\276\345\272\246\345\215\201\350\277\233\345\210\266\346\225\260.cpp" From b7fc77ed15d50a4f796be6532bbe1b45ff06df04 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Thu, 20 Nov 2025 00:10:25 +0800 Subject: [PATCH 09/25] modify code --- ...3\351\200\237\346\216\222\345\272\217.cpp" | 28 +++++++++++++++++++ ...51\235\236\351\200\222\345\275\222DFS.cpp" | 0 2 files changed, 28 insertions(+) create mode 100644 "\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" rename "\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" => "\351\235\236\351\200\222\345\275\222DFS.cpp" (100%) diff --git "a/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" "b/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" new file mode 100644 index 0000000..a0b88e5 --- /dev/null +++ "b/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" @@ -0,0 +1,28 @@ +#include +using namespace std; +mt19937 rng(random_device{}()); +vector arr; +int partition(int l, int r) +{ + int x = arr[l]; + int i = l, j = r + 1; + while (i < j) + { + while (++i <= r && arr[i] <= x) + ; + while (--j >= l && arr[j] >= x) + ; + if (i < j) + swap(arr[i], arr[j]); + } + swap(arr[i], arr[l]); + return i; +} +void quick_sort(int l, int r) +{ + if (l >= r) + return; + int mid = partition(l, r); + quick_sort(l, mid - 1); + quick_sort(mid + 1, r); +} \ No newline at end of file diff --git "a/\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" "b/\351\235\236\351\200\222\345\275\222DFS.cpp" similarity index 100% rename from "\351\235\236\351\200\222\345\275\222\347\211\210DFS.cpp" rename to "\351\235\236\351\200\222\345\275\222DFS.cpp" From 2e88ac3511a201d47a82c62f12439978ad7ec952 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Thu, 20 Nov 2025 10:03:26 +0800 Subject: [PATCH 10/25] modify code --- ...3\351\200\237\346\216\222\345\272\217.cpp" | 18 +++++-------- ...7\345\205\260\345\233\275\346\227\227.cpp" | 26 +++++++++++++++++++ ...3\351\200\237\346\216\222\345\272\217.cpp" | 26 +++++++++++++++++++ 3 files changed, 59 insertions(+), 11 deletions(-) create mode 100644 "\350\215\267\345\205\260\345\233\275\346\227\227.cpp" create mode 100644 "\351\232\217\346\234\272\345\277\253\351\200\237\346\216\222\345\272\217.cpp" diff --git "a/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" "b/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" index a0b88e5..ecbadc1 100644 --- "a/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" +++ "b/\346\234\264\347\264\240\345\277\253\351\200\237\346\216\222\345\272\217.cpp" @@ -4,19 +4,15 @@ mt19937 rng(random_device{}()); vector arr; int partition(int l, int r) { - int x = arr[l]; - int i = l, j = r + 1; - while (i < j) + int i = l + 1, j = r; + while (i <= j) { - while (++i <= r && arr[i] <= x) - ; - while (--j >= l && arr[j] >= x) - ; - if (i < j) - swap(arr[i], arr[j]); + if (arr[i] <= arr[l]) + i++; + else + swap(arr[i], arr[j--]); } - swap(arr[i], arr[l]); - return i; + return j; } void quick_sort(int l, int r) { diff --git "a/\350\215\267\345\205\260\345\233\275\346\227\227.cpp" "b/\350\215\267\345\205\260\345\233\275\346\227\227.cpp" new file mode 100644 index 0000000..b256d01 --- /dev/null +++ "b/\350\215\267\345\205\260\345\233\275\346\227\227.cpp" @@ -0,0 +1,26 @@ +#include +using namespace std; +mt19937 rng(random_device{}()); +vector arr; +pair part(int l, int r, int x) +{ + int i = l, j = l, k = r; + while (i <= k) + { + if (arr[i] == x) + i++; + else if (arr[i] < x) + swap(arr[i++], arr[j++]); + else if (arr[i] > x) + swap(arr[i], arr[k--]); + } + return {j, k}; +} +void quick_sort(int l, int r) +{ + if (l >= r) + return; + auto [L, R] = part(l, r, arr[l + rng() % (r - l + 1)]); + quick_sort(l, L - 1); + quick_sort(R + 1, r); +} \ No newline at end of file diff --git "a/\351\232\217\346\234\272\345\277\253\351\200\237\346\216\222\345\272\217.cpp" "b/\351\232\217\346\234\272\345\277\253\351\200\237\346\216\222\345\272\217.cpp" new file mode 100644 index 0000000..afa4e9c --- /dev/null +++ "b/\351\232\217\346\234\272\345\277\253\351\200\237\346\216\222\345\272\217.cpp" @@ -0,0 +1,26 @@ +#include +using namespace std; +mt19937 rng(random_device{}()); +vector arr; +int part(int l, int r, int p) +{ + swap(arr[p], arr[l]); + int i = l + 1, j = r; + while (i <= j) + { + if (arr[i] <= arr[l]) + i++; + else + swap(arr[i], arr[j--]); + } + swap(arr[j], arr[l]); + return j; +} +void quick_sort(int l, int r) +{ + if (l >= r) + return; + int mid = part(l, r, l + rng() % (r - l + 1)); + quick_sort(l, mid - 1); + quick_sort(mid + 1, r); +} \ No newline at end of file From 63bf1ee8732d914098fec3a07cbb48fd1f111bf0 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Sun, 23 Nov 2025 21:40:25 +0800 Subject: [PATCH 11/25] modify code --- KMP.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 KMP.cpp diff --git a/KMP.cpp b/KMP.cpp new file mode 100644 index 0000000..cc1e126 --- /dev/null +++ b/KMP.cpp @@ -0,0 +1,34 @@ +// KMP +#include +using namespace std; +int main() +{ + string s, t; + cin >> s >> t; + int n = s.size(); + int m = t.size(); + vector nex(m + 1); + // 求next数组 + for (int i = 1, j = 0; i < m; i++) + { + while (j && t[i] != t[j]) + j = nex[j]; + if (t[i] == t[j]) + j++; + nex[i + 1] = j; + } + // 输出匹配位置(下标从1开始) + for (int i = 0, j = 0; i < n; i++) + { + while (j && s[i] != t[j]) + j = nex[j]; + if (s[i] == t[j]) + j++; + if (j == m) + cout << i - m + 2 << "\n"; + } + for (int i = 1; i <= m; i++) + cout << nex[i] << " "; + cout << "\n"; + return 0; +} \ No newline at end of file From fcb8c63a5d484c51d0a58fc2f45e713fc37e7d45 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Mon, 24 Nov 2025 00:42:29 +0800 Subject: [PATCH 12/25] modify code --- Bellman-Ford.cpp | 42 +++++++++++++++++++ FHQ_Treap.cpp => FHQ-Treap.cpp | 0 ...6\345\210\206\347\272\246\346\235\237.cpp" | 42 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 Bellman-Ford.cpp rename FHQ_Treap.cpp => FHQ-Treap.cpp (100%) create mode 100644 "\345\267\256\345\210\206\347\272\246\346\235\237.cpp" diff --git a/Bellman-Ford.cpp b/Bellman-Ford.cpp new file mode 100644 index 0000000..5fc78fa --- /dev/null +++ b/Bellman-Ford.cpp @@ -0,0 +1,42 @@ +#include +using namespace std; +int main() +{ + int n, m; + cin >> n >> m; + vector> e; + vector dis(n + 1, 1e9); + dis[0] = 0; + for (int i = 0; i < m; i++) + { + int u, v, w; + cin >> u >> v >> w; + e.push_back({v, u, w}); + } + // 0为超级源点 + for (int i = 1; i < n + 1; i++) + e.push_back({0, i, 0}); + // bellman-ford + for (int i = 0; i < n; i++) + { + for (auto [u, v, w] : e) + { + if (dis[v] > dis[u] + w) + dis[v] = dis[u] + w; + } + } + for (auto [u, v, w] : e) + { + if (dis[v] > dis[u] + w) + { + // 存在负环 + cout << "NO\n"; + return 0; + } + } + // 输出单源最短路 + for (int i = 1; i < n + 1; i++) + cout << dis[i] << " "; + cout << "\n"; + return 0; +} \ No newline at end of file diff --git a/FHQ_Treap.cpp b/FHQ-Treap.cpp similarity index 100% rename from FHQ_Treap.cpp rename to FHQ-Treap.cpp diff --git "a/\345\267\256\345\210\206\347\272\246\346\235\237.cpp" "b/\345\267\256\345\210\206\347\272\246\346\235\237.cpp" new file mode 100644 index 0000000..6cc158e --- /dev/null +++ "b/\345\267\256\345\210\206\347\272\246\346\235\237.cpp" @@ -0,0 +1,42 @@ +// 与 Bellman-Ford 和 SPFA 的算法完全等价 +#include +using namespace std; +int main() +{ + int n, m; + cin >> n >> m; + vector> e; + vector dis(n + 1, 1e9); + dis[0] = 0; + for (int i = 0; i < m; i++) + { + int u, v, w; + cin >> u >> v >> w; + e.push_back({v, u, w}); + } + for (int i = 1; i < n + 1; i++) + e.push_back({0, i, 0}); + // bellman-ford + for (int i = 0; i < n; i++) + { + for (auto [u, v, w] : e) + { + if (dis[v] > dis[u] + w) + dis[v] = dis[u] + w; + } + } + for (auto [u, v, w] : e) + { + if (dis[v] > dis[u] + w) + { + // 存在负环,方程无解 + cout << "NO\n"; + return 0; + } + } + // 差分不等式的一个解集 + for (int i = 1; i < n + 1; i++) + cout << dis[i] << " "; + cout << "\n"; + return 0; +} \ No newline at end of file From a1e21c4f98f9bef865696d2247270dd363e95497 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Tue, 25 Nov 2025 21:33:07 +0800 Subject: [PATCH 13/25] modify code --- SPFA.cpp | 38 +++++++++++ ...2\346\225\260\346\216\222\345\272\217.cpp" | 32 +++++++++ "\345\240\206\346\216\222\345\272\217.cpp" | 66 +++++++++++++++++++ ...2\345\271\266\346\216\222\345\272\217.cpp" | 18 +++++ ...2\345\271\266\346\216\222\345\272\217.cpp" | 27 ++++++++ 5 files changed, 181 insertions(+) create mode 100644 SPFA.cpp create mode 100644 "\345\237\272\346\225\260\346\216\222\345\272\217.cpp" create mode 100644 "\345\240\206\346\216\222\345\272\217.cpp" create mode 100644 "\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" create mode 100644 "\351\235\236\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" diff --git a/SPFA.cpp b/SPFA.cpp new file mode 100644 index 0000000..ab30eba --- /dev/null +++ b/SPFA.cpp @@ -0,0 +1,38 @@ +#include +using namespace std; +/** + * @brief SPFA求单源最短路 + * + * @param g 存储节点编号和长度的图 + * @param dis 最短路 + * @param s 源点编号 + * + * @return 是否有负环 + * + * @note 要求 g.size() == dis.size() + */ +bool spfa(vector>> &g, vector &dis, int s) +{ + int n = g.size(); + // 存储节点编号和松弛次数 + queue> q; + q.push({s, 0}); + while (q.size()) + { + auto [u, c] = q.front(); + q.pop(); + if (c >= n) + { + return false; + } + for (auto [v, w] : g[u]) + { + if (dis[v] < dis[u] + w) + { + dis[v] = dis[u] + w; + q.push({v, c + 1}); + } + } + } + return true; +} \ No newline at end of file diff --git "a/\345\237\272\346\225\260\346\216\222\345\272\217.cpp" "b/\345\237\272\346\225\260\346\216\222\345\272\217.cpp" new file mode 100644 index 0000000..3dc0e83 --- /dev/null +++ "b/\345\237\272\346\225\260\346\216\222\345\272\217.cpp" @@ -0,0 +1,32 @@ +#include +using namespace std; +/** + * @brief 基数排序 + * + * @param arr 源数组 + * @param base 底数(几进制) + * @param power 幂(几位) + * + */ +void radix_sort(vector &arr, int base, int power) +{ + int n = arr.size(); + // 基数计数(例如十进制下468的第1,2,3基数分别是4,6,8), 临时数组 + vector cnt(base), tmp(n); + for (int offset = 1; power > 0; power--, offset *= base) + { + fill(cnt.begin(), cnt.end(), 0); + // 统计不同基数的数的个数 + for (int i = 0; i < n; i++) + cnt[arr[i] / offset % base]++; + // 计算后的是每组的右边界 + for (int i = 1; i < base; i++) + cnt[i] += cnt[i - 1]; + // 每次读入临时数组的对应区域, 不同基数互不干扰 + for (int i = n - 1; i >= 0; i--) + tmp[--cnt[arr[i] / offset % base]] = arr[i]; + // 写回原数组 + for (int i = 0; i < n; i++) + arr[i] = tmp[i]; + } +} \ No newline at end of file diff --git "a/\345\240\206\346\216\222\345\272\217.cpp" "b/\345\240\206\346\216\222\345\272\217.cpp" new file mode 100644 index 0000000..c47cad0 --- /dev/null +++ "b/\345\240\206\346\216\222\345\272\217.cpp" @@ -0,0 +1,66 @@ +#include +using namespace std; +/** + * @brief 堆元素上升 + * + * @param arr 源堆 + * @param i 待上升元素 + */ +void heap_up(vector &arr, int i) +{ + while (i > 0) + { + int f = (i - 1) / 2; + if (arr[i] > arr[f]) + { + swap(arr[i], arr[f]); + i = f; + } + else + break; + } +} +/** + * @brief 堆元素下沉 + * + * @param arr 源堆 + * @param i 待下沉元素 + * @param n 堆大小 + */ +void heap_down(vector &arr, int i, int n) +{ + while (i * 2 + 1 < n) + { + int l = i * 2 + 1; + int r = i * 2 + 2; + // 从i,l,r三者选最优者(即arr[x]最大) + // 采用两两比较取最大 + int best = arr[l] > arr[i] ? l : i; + best = r < n && arr[r] > arr[best] ? r : best; + if (best != i) + { + swap(arr[best], arr[i]); + i = best; + } + else + break; + } +} +/** + * @brief 堆排序(大根堆) + * + * @param arr 待排序数组 + */ +void heap_sort(vector &arr) +{ + int n = arr.size(); + // 首先建堆 + for (int i = 0; i < n; i++) + heap_up(arr, i); + // 将堆顶元素arr[0]与末尾元素arr[i]交换, 此时堆顶成为末尾最大 + for (int i = n - 1; i >= 0; i--) + { + swap(arr[0], arr[i]); + heap_down(arr, 0, i); + } +} \ No newline at end of file diff --git "a/\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" "b/\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" new file mode 100644 index 0000000..e45ab9d --- /dev/null +++ "b/\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" @@ -0,0 +1,18 @@ +#include +using namespace std; +vector arr, tmp; +void merge_sort(int l, int r) +{ + int mid = (l + r) / 2; + merge_sort(l, mid); + merge_sort(mid + 1, r); + for (int i = l, j = l, k = mid + 1; i <= r; i++) + { + if (j <= mid && (k > r || arr[j] <= arr[k])) + tmp[i] = arr[j++]; + else + tmp[i] = arr[k++]; + } + for (int i = l; i <= r; i++) + arr[i] = tmp[i]; +} \ No newline at end of file diff --git "a/\351\235\236\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" "b/\351\235\236\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" new file mode 100644 index 0000000..a5577e7 --- /dev/null +++ "b/\351\235\236\351\200\222\345\275\222\345\275\222\345\271\266\346\216\222\345\272\217.cpp" @@ -0,0 +1,27 @@ +#include +using namespace std; +void merge_sort(vector &arr) +{ + int n = arr.size(); + vector tmp(n); + for (int step = 1; step < n; step *= 2) + { + for (int i = 0; i * step < n; i++) + { + int l = i * 2 * step; + int mid = min((i * 2 + 1) * step, n); + int r = min((i * 2 + 2) * step, n); + if (mid == r) + continue; + for (int i = l, j = l, k = mid; i < r; i++) + { + if (j < mid && (k >= r || arr[j] <= arr[k])) + tmp[i] = arr[j++]; + else + tmp[i] = arr[k++]; + } + for (int i = l; i < r; i++) + arr[i] = tmp[i]; + } + } +} \ No newline at end of file From c88e640e01c9ed86c5d76eb4b6c0f3bc57e71b43 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Thu, 27 Nov 2025 09:35:08 +0800 Subject: [PATCH 14/25] modify code --- ...1\346\234\200\347\237\255\350\267\257.cpp" | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 "\345\220\214\344\275\231\346\234\200\347\237\255\350\267\257.cpp" diff --git "a/\345\220\214\344\275\231\346\234\200\347\237\255\350\267\257.cpp" "b/\345\220\214\344\275\231\346\234\200\347\237\255\350\267\257.cpp" new file mode 100644 index 0000000..9aa8ab0 --- /dev/null +++ "b/\345\220\214\344\275\231\346\234\200\347\237\255\350\267\257.cpp" @@ -0,0 +1,37 @@ +#include +using namespace std; +int main() +{ + long long h; + int x, y, z; + cin >> h >> x >> y >> z; + vector>> g(x); + for (int i = 0; i < x; i++) + { + g[i].push_back({(i + y) % x, y}); + g[i].push_back({(i + z) % x, z}); + } + vector dis(x, h); + dis[0] = 0; + priority_queue, vector>, greater<>> q; + q.push({dis[0], 0}); + while (q.size()) + { + auto [d, u] = q.top(); + q.pop(); + for (auto [v, w] : g[u]) + { + if (dis[v] > d + w) + { + dis[v] = d + w; + q.push({dis[v], v}); + } + } + } + long long ans = 0; + for (int i = 0; i < x; i++) + if (h - 1 >= dis[i]) + ans += (h - 1 - dis[i]) / x + 1; + cout << ans << "\n"; + return 0; +} \ No newline at end of file From b4edda1ed3f115df90e2a3623b70df7ea379431d Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Thu, 27 Nov 2025 10:58:39 +0800 Subject: [PATCH 15/25] modify code --- "AVL\346\240\221.cpp" | 372 ++++++++++++++++++++---------------------- 1 file changed, 173 insertions(+), 199 deletions(-) diff --git "a/AVL\346\240\221.cpp" "b/AVL\346\240\221.cpp" index ad46667..9dfa76a 100644 --- "a/AVL\346\240\221.cpp" +++ "b/AVL\346\240\221.cpp" @@ -1,256 +1,230 @@ -// https://www.luogu.com.cn/problem/P3369 +/** + * @brief AVL树 + * + * @note 节点编号从1开始 + */ #include using namespace std; -using ll = long long; -using ull = unsigned long long; -using pii = pair; -#define IOS \ - ios::sync_with_stdio(0); \ - cin.tie(0); \ - cout.tie(0) -#define rep(i, j, k) for (int i = j; i <= k; ++i) -#define rrep(i, j, k) for (int i = j; i >= k; --i) -#define clr(a, b) memset(a, b, sizeof(a)) -const int INF = 0x3f3f3f3f; -const int MOD = 1e9 + 7; -const double EPS = 1e-8; -const int N = 1e5 + 5; -int tn; -int root; -int key[N]; -int hei[N]; -int ls[N]; -int rs[N]; -int cnt[N]; -int siz[N]; -void upd(int x) +vector key, cnt, ls, rs, ht, sz; +int tot = 1; +/** + * @brief 更新高度和结点数 + */ +void upd(int u) { - siz[x] = siz[ls[x]] + siz[rs[x]] + cnt[x]; - hei[x] = max(hei[ls[x]], hei[rs[x]]) + 1; + ht[u] = max(ht[ls[u]], ht[rs[u]]) + 1; + sz[u] = sz[ls[u]] + sz[rs[u]] + cnt[u]; } -int lrot(int x) +/** + * @brief 左旋 + */ +int lrot(int u) { - int r = rs[x]; - rs[x] = ls[r]; - ls[r] = x; - upd(x); + int r = rs[u]; + rs[u] = ls[r]; + ls[r] = u; + upd(u); upd(r); return r; } -int rrot(int x) +/** + * @brief 右旋 + */ +int rrot(int u) { - int l = ls[x]; - ls[x] = rs[l]; - rs[l] = x; - upd(x); + int l = ls[u]; + ls[u] = rs[l]; + rs[l] = u; + upd(u); upd(l); return l; } -int maintain(int x) +/** + * @brief 根据平衡因子通过旋转调整树高 + */ +int balance(int u) { - int l = ls[x]; - int r = rs[x]; - int lh = hei[l]; - int rh = hei[r]; + int lh = ht[ls[u]]; + int rh = ht[rs[u]]; if (lh - rh > 1) { - if (hei[ls[l]] >= hei[rs[l]]) + if (ht[rs[ls[u]]] > ht[ls[ls[u]]]) { - x = rrot(x); - } - else - { - ls[x] = lrot(l); - x = rrot(x); + ls[u] = lrot(ls[u]); + return rrot(u); } + return rrot(u); } - else if (rh - lh > 1) + if (rh - lh > 1) { - if (hei[rs[r]] >= hei[ls[r]]) - { - x = lrot(x); - } - else + if (ht[ls[rs[u]]] > ht[rs[rs[u]]]) { - rs[x] = rrot(r); - x = lrot(x); + rs[u] = rrot(rs[u]); + return lrot(u); } + return lrot(u); } - return x; + return u; } -int add(int p, int x) +/** + * @brief 插入新节点 + * + * @param u 起始根节点 + * @param x 节点的键 + */ +int insert(int u, int x) { - if (!p) + if (u == 0) { - p = ++tn; - key[tn] = x; - cnt[tn] = 1; + u = tot++; + key[u] = x; + cnt[u] = 1; } - else if (key[p] == x) + else if (key[u] == x) { - ++cnt[p]; + cnt[u]++; } - else if (key[p] < x) - { - rs[p] = add(rs[p], x); - } - else - { - ls[p] = add(ls[p], x); - } - upd(p); - return maintain(p); + else if (key[u] < x) + rs[u] = insert(rs[u], x); + else if (key[u] > x) + ls[u] = insert(ls[u], x); + upd(u); + return balance(u); } -int del_mostlst(int p, int x) +/** + * @brief 摘取最右端的节点, 服务于remove函数 + * + * @param u 起始根节点 + */ +pair pick_mostright(int u) { - if (p == x) - { - return rs[p]; - } - else - { - ls[p] = del_mostlst(ls[p], x); - } - upd(p); - return maintain(p); + if (rs[u] == 0) + return {ls[u], u}; + auto [r, v] = pick_mostright(rs[u]); + rs[u] = r; + upd(u); + return {balance(u), v}; } -int del(int p, int x) +/** + * @brief 删除节点 + * + * @param x 待删节点的键 + */ +int remove(int u, int x) { - if (!p) - { + if (u == 0) return 0; - } - else if (key[p] == x) - { - if (cnt[p] > 1) - { - --cnt[p]; - } - else - { - if (!ls[p] && !rs[p]) - { - return 0; - } - else if (!ls[p] && rs[p]) - { - p = rs[p]; - } - else if (ls[p] && !rs[p]) - { - p = ls[p]; - } - else - { - int rl = rs[p]; - while (ls[rl]) - rl = ls[rl]; - rs[rl] = del_mostlst(rs[p], rl); - ls[rl] = ls[p]; - p = rl; - } - } - } - else if (key[p] < x) + if (key[u] != x) { - rs[p] = del(rs[p], x); + if (key[u] < x) + rs[u] = remove(rs[u], x); + else if (key[u] > x) + ls[u] = remove(ls[u], x); + upd(u); + return balance(u); } - else + if (cnt[u] > 1) { - ls[p] = del(ls[p], x); + cnt[u]--; + upd(u); + return u; } - upd(p); - return maintain(p); + if (ls[u] == 0 && rs[u] == 0) + return 0; + if (ls[u] == 0) + return rs[u]; + if (rs[u] == 0) + return ls[u]; + auto [v, w] = pick_mostright(ls[u]); + ls[w] = v; + rs[w] = rs[u]; + upd(w); + return balance(w); } -int get_rank(int p, int x) +/** + * @brief 获取节点排名(从0开始) + * + * @param x 节点的键 + */ +int get_rank(int u, int x) { - if (!p) - return 1; - else if (key[p] >= x) - return get_rank(ls[p], x); - else - return siz[ls[p]] + cnt[p] + get_rank(rs[p], x); + if (u == 0) + return 0; + if (key[u] < x) + return sz[ls[u]] + cnt[u] + get_rank(rs[u], x); + return get_rank(ls[u], x); } -int get_key(int p, int x) +/** + * @brief 获取指定排名的节点键 + * + * @param rk 节点排名 + */ +int get_key(int u, int rk) { - if (siz[ls[p]] >= x) - return get_key(ls[p], x); - else if (siz[ls[p]] + cnt[p] < x) - return get_key(rs[p], x - siz[ls[p]] - cnt[p]); - else - return key[p]; + if (sz[ls[u]] + cnt[u] <= rk) + return get_key(rs[u], rk - sz[ls[u]] - cnt[u]); + if (sz[ls[u]] > rk) + return get_key(ls[u], rk); + return key[u]; } -int get_pre(int p, int x) +/** + * @brief 获取节点前驱 + * + * @param x 节点的键 + */ +int get_pre(int u, int x) { - if (!p) - return INT_MIN; - else if (key[p] >= x) - return get_pre(ls[p], x); - else - return max(key[p], get_pre(rs[p], x)); + if (u == 0) + return -1e9; + if (key[u] < x) + return max(get_pre(rs[u], x), key[u]); + return get_pre(ls[u], x); } -int get_post(int p, int x) +/** + * @brief 获取节点后继 + * + * @param x 节点的键 + */ +int get_post(int u, int x) { - if (!p) - return INT_MAX; - else if (key[p] <= x) - return get_post(rs[p], x); - else - return min(key[p], get_post(ls[p], x)); + if (u == 0) + return 1e9; + if (key[u] > x) + return min(get_post(ls[u], x), key[u]); + return get_post(rs[u], x); } -inline void solve() +/** + * @brief 使用示例 + * + * @note 测试链接: https://www.luogu.com.cn/problem/P3369 + */ +int main() { - tn = 0; - root = 0; - clr(key, 0); - clr(hei, 0); - clr(ls, 0); - clr(rs, 0); - clr(cnt, 0); - clr(siz, 0); - int m; - scanf("%d", &m); - int op, x; - while (m--) + int n; + cin >> n; + key.resize(n + 1); + cnt.resize(n + 1); + ls.resize(n + 1); + rs.resize(n + 1); + ht.resize(n + 1); + sz.resize(n + 1); + int root = 0; + for (int i = 0; i < n; i++) { - scanf("%d%d", &op, &x); + int op, x; + cin >> op >> x; if (op == 1) - { - root = add(root, x); - } + root = insert(root, x); else if (op == 2) - { - root = del(root, x); - } + root = remove(root, x); else if (op == 3) - { - printf("%d\n", get_rank(root, x)); - } + cout << get_rank(root, x) + 1 << "\n"; else if (op == 4) - { - printf("%d\n", get_key(root, x)); - } + cout << get_key(root, x - 1) << "\n"; else if (op == 5) - { - printf("%d\n", get_pre(root, x)); - } + cout << get_pre(root, x) << "\n"; else - { - printf("%d\n", get_post(root, x)); - } - } -} -inline void init() -{ -} -int main() -{ - IOS; - init(); - int t = 1; - while (t--) - { - solve(); + cout << get_post(root, x) << "\n"; } return 0; } \ No newline at end of file From 929a317667568317766b1defd24f952297898ea2 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Thu, 27 Nov 2025 13:55:15 +0800 Subject: [PATCH 16/25] modify code --- ...6\351\200\232\345\210\206\351\207\217.cpp" | 85 +++++++++++++++++++ ...6\351\200\232\345\210\206\351\207\217.cpp" | 78 +++++++++++++++++ 2 files changed, 163 insertions(+) create mode 100644 "\347\202\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" create mode 100644 "\350\276\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" diff --git "a/\347\202\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" "b/\347\202\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" new file mode 100644 index 0000000..6069c84 --- /dev/null +++ "b/\347\202\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" @@ -0,0 +1,85 @@ +#include +using namespace std; +vector> g, vdccs; +vector dfn, low; +vector cut; +stack stk; +int tot, rt; +// 求点双连通分量(vDCC) +void tarjan(int u) +{ + dfn[u] = low[u] = tot++; + stk.push(u); + // 特判一个点的vDCC + if (u == rt && g[u].empty()) + { + vdccs.push_back({u}); + return; + } + int son = 0; + for (auto v : g[u]) + { + if (dfn[v] == -1) + { + tarjan(v); + low[u] = min(low[u], low[v]); + // 找到vDCC + if (dfn[u] > low[v]) + continue; + son++; + // 找到割点 + if (u != rt || son > 1) + cut[u] = true; + vdccs.push_back({}); + int w; + do + { + w = stk.top(); + stk.pop(); + vdccs.back().push_back(w); + } while (w != v); + vdccs.back().push_back(u); + } + else + { + low[u] = min(low[u], dfn[v]); + } + } +} +/** + * @brief 使用示例 + * + * @note 测试链接: https://www.luogu.com.cn/problem/P8435 + */ +int main() +{ + int n, m; + cin >> n >> m; + g.resize(n); + dfn.resize(n, -1); + low.resize(n, -1); + cut.resize(n); + for (int i = 0; i < m; ++i) + { + int u, v; + cin >> u >> v; + u--; + v--; + if (u == v) + continue; + g[u].push_back(v); + g[v].push_back(u); + } + for (int i = 0; i < n; ++i) + if (dfn[i] == -1) + tarjan(rt = i); + cout << vdccs.size() << "\n"; + for (auto &vdcc : vdccs) + { + cout << vdcc.size() << " "; + for (auto u : vdcc) + cout << u + 1 << " "; + cout << "\n"; + } + return 0; +} \ No newline at end of file diff --git "a/\350\276\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" "b/\350\276\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" new file mode 100644 index 0000000..83b611d --- /dev/null +++ "b/\350\276\271\345\217\214\350\277\236\351\200\232\345\210\206\351\207\217.cpp" @@ -0,0 +1,78 @@ +#include +using namespace std; +vector> g, edccs; +vector dfn, low; +vector instk; +stack stk; +int tot; +// tarjan算法求边双连通分量(eDCCs) +void tarjan(int u, int fa) +{ + dfn[u] = low[u] = tot++; + stk.push(u); + instk[u] = true; + // 是否访问到反边 + bool fa_edge = false; + for (auto v : g[u]) + { + if (dfn[v] == -1) + { + tarjan(v, u); + low[u] = min(low[u], low[v]); + // 找到割边 + // if (low[v] > dfn[v]); + } + else if (instk[v] && (v != fa || fa_edge)) + low[u] = min(low[u], dfn[v]); + else + fa_edge = true; + } + if (dfn[u] != low[u]) + return; + edccs.push_back({}); + int v; + do + { + v = stk.top(); + stk.pop(); + edccs + .back() + .push_back(v); + instk[v] = false; + } while (v != u); +} +/** + * @brief 使用示例 + * + * @note 测试链接: https://www.luogu.com.cn/problem/P8436 + */ +int main() +{ + int n, m; + cin >> n >> m; + g.resize(n); + dfn.resize(n, -1); + low.resize(n, -1); + instk.resize(n); + for (int i = 0; i < m; ++i) + { + int u, v; + cin >> u >> v; + u--; + v--; + g[u].push_back(v); + g[v].push_back(u); + } + for (int i = 0; i < n; ++i) + if (dfn[i] == -1) + tarjan(i, -1); + cout << edccs.size() << "\n"; + for (auto &edcc : edccs) + { + cout << edcc.size() << " "; + for (auto u : edcc) + cout << u + 1 << " "; + cout << "\n"; + } + return 0; +} \ No newline at end of file From edcccafda7e82d9f2f17e0afe990155cd0faee3e Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Thu, 27 Nov 2025 14:30:07 +0800 Subject: [PATCH 17/25] modify code --- ...1\345\274\217\345\220\210\345\271\266.cpp" | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 "\346\240\221\344\270\212\345\220\257\345\217\221\345\274\217\345\220\210\345\271\266.cpp" diff --git "a/\346\240\221\344\270\212\345\220\257\345\217\221\345\274\217\345\220\210\345\271\266.cpp" "b/\346\240\221\344\270\212\345\220\257\345\217\221\345\274\217\345\220\210\345\271\266.cpp" new file mode 100644 index 0000000..1b7ce2c --- /dev/null +++ "b/\346\240\221\344\270\212\345\220\257\345\217\221\345\274\217\345\220\210\345\271\266.cpp" @@ -0,0 +1,137 @@ +#include +using namespace std; +vector> g; +vector c, fa, sz, son, ans, cnt; +int cur; +/** + * @brief 树链剖分 + * + * @param u 根节点 + * @param f 父亲 + */ +void build(int u, int f) +{ + fa[u] = f; + sz[u] = 1; + for (int v : g[u]) + { + if (v == f) + continue; + build(v, u); + sz[u] += sz[v]; + // 求重儿子 + if (son[u] == -1 || sz[son[u]] < sz[v]) + son[u] = v; + } +} +/** + * @brief 添加信息 + * + * @param u 根节点 + */ +void add(int u) +{ + // 更新种类数 + if (cnt[c[u]]++ == 0) + cur++; + for (int v : g[u]) + { + if (v == fa[u]) + continue; + add(v); + } +} +/** + * @brief 删除信息 + * + * @param u 根节点 + */ +void del(int u) +{ + // 更新种类数 + if (cnt[c[u]]-- == 1) + cur--; + for (int v : g[u]) + { + if (v == fa[u]) + continue; + del(v); + } +} +/** + * @brief 求答案 + * + * @param u 起始根节点 + * @param keep 是否保留cnt中的信息 + */ +void setans(int u, bool keep) +{ + // 先对轻儿子求答案, 不保留信息, 互不干扰 + for (int v : g[u]) + { + if (v == fa[u] || v == son[u]) + continue; + setans(v, 0); + } + // 对重儿子求答案 + if (son[u] != -1) + setans(son[u], 1); + // 对自己求答案 + if (cnt[c[u]]++ == 0) + cur++; + // 再次对轻儿子求答案, 保留信息, 即合并 + for (int v : g[u]) + { + if (v == fa[u] || v == son[u]) + continue; + add(v); + } + // 最终答案 + ans[u] = cur; + // 响应keep命令 + if (!keep) + del(u); +} +/** + * @brief 使用示例 + * + * @note 测试链接: https://www.luogu.com.cn/problem/U41492 + */ +int main() +{ + int n; + cin >> n; + g.resize(n); + c.resize(n); + fa.resize(n, -1); + sz.resize(n); + son.resize(n, -1); + ans.resize(n); + cnt.resize(1e5); + for (int i = 0; i < n - 1; ++i) + { + int u, v; + cin >> u >> v; + --u; + --v; + g[u].push_back(v); + g[v].push_back(u); + } + for (int i = 0; i < n; ++i) + { + cin >> c[i]; + c[i]--; + } + build(0, -1); + setans(0, 0); + int m; + cin >> m; + for (int i = 0; i < m; ++i) + { + int u; + cin >> u; + --u; + cout << ans[u] << "\n"; + } + return 0; +} \ No newline at end of file From c645fcfd6ca049398c87d01e7f9c673a4eb74ce3 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Fri, 28 Nov 2025 13:50:05 +0800 Subject: [PATCH 18/25] modify code --- acam.cpp | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 acam.cpp diff --git a/acam.cpp b/acam.cpp new file mode 100644 index 0000000..5b86aef --- /dev/null +++ b/acam.cpp @@ -0,0 +1,135 @@ +#include +using namespace std; +const int N = 2e5; +vector pat; // 模式串 +string str; // 源串 +vector> trie; // Trie +vector fail; // 失配指针, 指向最长后缀的头 +vector en; // 每个模式串的结束位置 +vector cnt; // 词频 +int tot = 1; // Trie节点总数, 0为根节点 +vector> g; +/** + * @brief Trie插入串 + * + * @param idx 串编号 + * @param s 待插入的串 + */ +void insert(int idx, string s) +{ + int u = 0; + for (char c : s) + { + int i = c - 'a'; + if (trie[u][i] == 0) + { + // 新建节点 + trie.push_back(vector(26)); + trie[u][i] = tot++; + } + u = trie[u][i]; + } + en[idx] = u; +} +/** + * @brief 设置fail指针 + */ +void set_fail() +{ + // BFS设置fail指针 + queue q; + for (int i = 0; i < 26; i++) + if (trie[0][i] != 0) + q.push(trie[0][i]); + while (q.size()) + { + int u = q.front(); + q.pop(); + for (int i = 0; i < 26; i++) + { + if (trie[u][i] == 0) + // AC自动机优化: 设置直通表, 压缩fail指针跳转长度 + trie[u][i] = trie[fail[u]][i]; + else + { + // 为子节点设置fail指针 + fail[trie[u][i]] = trie[fail[u]][i]; + // 压入队列 + q.push(trie[u][i]); + } + } + } +} +/** + * @brief 统计词频 + */ +void set_cnt() +{ + int u = 0; + for (char c : str) + { + int i = c - 'a'; + u = trie[u][i]; + cnt[u]++; + } +} +/** + * @brief 统计答案, 直接在词频上做 + */ +void set_ans() +{ + // 栈优化, 也可用递归做 + vector vis(tot); + stack st; + st.push(0); + while (st.size()) + { + int u = st.top(); + if (!vis[u]) + { + // 儿子未处理 + vis[u] = true; + for (int v : g[u]) + st.push(v); + } + else + { + // 儿子已处理, 轮到自己 + st.pop(); + for (int v : g[u]) + cnt[u] += cnt[v]; + } + } +} +/** + * @brief 使用示例 + * + * @note 测试链接: https://www.luogu.com.cn/problem/P5357 + */ +int main() +{ + int n; + cin >> n; + pat.resize(n); + en.resize(n); + // 0为根节点 + trie.push_back(vector(26)); + for (int i = 0; i < n; i++) + { + cin >> pat[i]; + insert(i, pat[i]); + } + fail.resize(tot); + cnt.resize(tot); + g.resize(tot); + set_fail(); + cin >> str; + set_cnt(); + // 根据fail建反图 + for (int i = 1; i < tot; i++) + g[fail[i]].push_back(i); + set_ans(); + for (int i = 0; i < n; i++) + cout << cnt[en[i]] << "\n"; + return 0; +} \ No newline at end of file From c692773d63952ffc5b39ebbc8cf2483b2e746a38 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Sat, 29 Nov 2025 00:41:49 +0800 Subject: [PATCH 19/25] modify code --- Trie.cpp | 77 ++++++++----------- ...345\275\222\346\225\260\344\275\215DP.cpp" | 61 +++++++++++++++ ...345\275\222\346\225\260\344\275\215DP.cpp" | 51 ++++++++++++ 3 files changed, 143 insertions(+), 46 deletions(-) create mode 100644 "\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" create mode 100644 "\351\235\236\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" diff --git a/Trie.cpp b/Trie.cpp index b7ddafa..5ad115b 100644 --- a/Trie.cpp +++ b/Trie.cpp @@ -1,81 +1,66 @@ -// https://www.luogu.com.cn/problem/P8306 #include using namespace std; -using ll = long long; -using pii = pair; -#define rep(i, j, k) for (int i = (j); i <= (k); ++i) -#define rrep(i, j, k) for (int i = (j); i >= (k); --i) -const int INF = 0x3f3f3f3f; -const int MOD = 1e9 + 7; -const int N = 3e6 + 5; -int tot; -int nex[N][63]; -int cnt[N], chi[128]; -void insert(const string &s) +vector> trie; +vector cnt; +/** + * @brief 建Trie树, 插入串 + */ +void insert(string s) { - int p = 1; - cnt[p]++; + int u = 0; for (char c : s) { - if (!nex[p][chi[c]]) + cnt[u]++; + if (trie[u][c] == 0) { - nex[p][chi[c]] = ++tot; - memset(nex[tot], 0, sizeof(nex[tot])); - cnt[tot] = 0; + trie[u][c] = trie.size(); + trie.push_back(vector(128)); + cnt.push_back(0); } - p = nex[p][chi[c]]; - cnt[p]++; + u = trie[u][c]; } + cnt[u]++; } -int query(const string &s) +/** + * @brief 查询以s为前缀的串的个数 + */ +int query(string s) { - int p = 1; + int u = 0; for (char c : s) { - if (!nex[p][chi[c]]) - { + if (trie[u][c] == 0) return 0; - } - p = nex[p][chi[c]]; + u = trie[u][c]; } - return cnt[p]; + return cnt[u]; } void solve() { - tot = 1; - memset(nex[1], 0, sizeof(nex[1])); - cnt[1] = 0; + trie.clear(); + cnt.clear(); + trie.resize(1, vector(128)); + cnt.resize(1); int n, q; cin >> n >> q; - string s; - rep(i, 1, n) + for (int i = 0; i < n; i++) { + string s; cin >> s; insert(s); } - rep(i, 1, q) + for (int i = 0; i < q; i++) { + string s; cin >> s; cout << query(s) << "\n"; } } -void init() -{ - rep(i, 1, 26) chi[i - 1 + 'a'] = i; - rep(i, 27, 52) chi[i - 27 + 'A'] = i; - rep(i, 53, 62) chi[i - 53 + '0'] = i; -} int main() { - ios::sync_with_stdio(0); - cin.tie(0); - cout.tie(0); - init(); - int t = 1; + int t; cin >> t; while (t--) - { solve(); - } return 0; } \ No newline at end of file diff --git "a/\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" "b/\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" new file mode 100644 index 0000000..402e812 --- /dev/null +++ "b/\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" @@ -0,0 +1,61 @@ +#include +using namespace std; +using ll = long long; +vector num(19); +vector>> dp; +/** + * @brief 记忆化搜索 + * @param n 当前位置 + * @param la 上一个数 + * @param st 是否已经遇到非零 + * @param lim 是否受到约束 + */ +ll dfs(int n, int la, bool st, bool lim) +{ + if (n < 0) + // 返回 1 也可以 + return st; + // 返回未约束且已记录的值 + if (!lim && dp[n][la][st] != -1) + return dp[n][la][st]; + ll res = 0; + // 选上界 + int up = lim ? num[n] : 9; + for (int i = 0; i <= up; i++) + // 满足题中条件 + if (!st || abs(i - la) >= 2) + res += dfs(n - 1, i, st || i, lim && i == up); + // 只记录未约束的值 + if (!lim) + dp[n][la][st] = res; + return res; +} +/** + * @brief 返回小等于x且满足题意的数的个数 + * @param x 上界 + */ +ll f(ll x) +{ + dp.clear(); + dp.resize(20, vector>(10, vector(2, -1))); + for (int i = 0; i < 19; i++) + { + num[i] = x % 10; + x /= 10; + } + ll res = dfs(18, 0, false, true); + return res; +} +/** + * @brief 示例 + * @note 链接: https://www.luogu.com.cn/problem/P13085 + */ +int main() +{ + ll a, b; + cin >> a >> b; + ll f2 = f(b); + ll f1 = f(a - 1); + cout << f2 - f1 << "\n"; + return 0; +} \ No newline at end of file diff --git "a/\351\235\236\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" "b/\351\235\236\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" new file mode 100644 index 0000000..385f71e --- /dev/null +++ "b/\351\235\236\351\200\222\345\275\222\346\225\260\344\275\215DP.cpp" @@ -0,0 +1,51 @@ +#include +using namespace std; +using ll = long long; +/** + * @brief 非递归数位DP + * @param num 上界 + * @return 满足题意的数的个数 + */ +ll f(ll num) +{ + vector arr(19); + for (int i = 0; i < 19; i++) + { + arr[i] = num % 10; + num /= 10; + } + // dp[位置][末尾的数][是否遇到非零][是否限制] + ll dp[20][10][2][2]{}; + dp[19][0][0][1] = 1; + for (int p = 18; p >= 0; p--) + for (int x = 0; x < 10; x++) + for (int s = 0; s < 2; s++) + for (int l = 0; l < 2; l++) + { + int up = l ? arr[p] : 9; + for (int y = 0; y <= up; y++) + { + if (!s || abs(y - x) >= 2) + dp[p][y][s || y][l && y == up] += dp[p + 1][x][s][l]; + } + } + ll ans = 0; + for (int x = 0; x < 10; x++) + for (int s = 0; s < 2; s++) + for (int l = 0; l < 2; l++) + ans += dp[0][x][s][l]; + return ans; +} +/** + * @brief 使用示例 + * @note 测试链接: https://www.luogu.com.cn/problem/P13085 + */ +int main() +{ + ll a, b; + cin >> a >> b; + ll ans1 = f(a - 1); + ll ans2 = f(b); + cout << ans2 - ans1 << "\n"; + return 0; +} \ No newline at end of file From 09c9f5c28b4e087900cbb1cab459f613d6036c11 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Sat, 29 Nov 2025 13:26:05 +0800 Subject: [PATCH 20/25] modify code --- ...C\350\207\252\345\212\250\346\234\272.cpp" | 0 Tarjan_LCA.cpp | 84 ++++++++----------- "\345\271\266\346\237\245\351\233\206.cpp" | 20 +++++ 3 files changed, 57 insertions(+), 47 deletions(-) rename acam.cpp => "AC\350\207\252\345\212\250\346\234\272.cpp" (100%) create mode 100644 "\345\271\266\346\237\245\351\233\206.cpp" diff --git a/acam.cpp "b/AC\350\207\252\345\212\250\346\234\272.cpp" similarity index 100% rename from acam.cpp rename to "AC\350\207\252\345\212\250\346\234\272.cpp" diff --git a/Tarjan_LCA.cpp b/Tarjan_LCA.cpp index 0012941..5bddb53 100644 --- a/Tarjan_LCA.cpp +++ b/Tarjan_LCA.cpp @@ -1,83 +1,73 @@ -// https://www.luogu.com.cn/problem/P3379 #include using namespace std; -using ll = long long; -using pii = pair; -#define rep(i, j, k) for (int i = (j); i <= (k); ++i) -#define rrep(i, j, k) for (int i = (j); i >= (k); --i) -const int INF = 0x3f3f3f3f; -const int MOD = 1e9 + 7; +vector pre; vector> g; vector>> query; -vector vis, ans, pre; -int fin(int u) +vector vis; +vector ans; +void dsu_init(int n) { - return pre[u] = pre[u] == u ? u : fin(pre[u]); + pre.resize(n); + for (int i = 0; i < n; i++) + pre[i] = i; } -void uni(int u, int v) +int dsu_find(int u) { - u = fin(u); - v = fin(v); - pre[u] = v; + return pre[u] = pre[u] == u ? u : dsu_find(pre[u]); } +/** + * @brief Tarjan求LCA + * @param u 子树根节点 + */ void tarjan(int u) { - vis[u] = 1; - for (auto v : g[u]) - { + vis[u] = true; + for (int v : g[u]) if (!vis[v]) { + // 先求子树再连边, 隔离环境求最近 tarjan(v); pre[v] = u; } - } + // 离线查询 for (auto [v, i] : query[u]) - { if (vis[v]) - { - ans[i] = fin(v); - } - } + // 已经访问过的在同一个子树, 可图解 + ans[i] = dsu_find(v); } -void solve() +/** + * @brief 测试链接: https://www.luogu.com.cn/problem/P3379 + */ +int main() { int n, m, s; cin >> n >> m >> s; - g.resize(n + 1); - query.resize(n + 1); - vis.resize(n + 1); - pre.resize(n + 1); - ans.resize(n + 1); - for (int i = 1; i <= n; ++i) - pre[i] = i; - for (int i = 1; i < n; ++i) + s--; + dsu_init(n); + g.resize(n); + query.resize(m); + vis.resize(n); + ans.resize(m); + for (int i = 0; i < n - 1; i++) { int u, v; cin >> u >> v; + u--; + v--; g[u].push_back(v); g[v].push_back(u); } - for (int i = 1; i <= m; ++i) + for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; + u--; + v--; query[u].push_back({v, i}); query[v].push_back({u, i}); } tarjan(s); - for (int i = 1; i <= m; ++i) - cout << ans[i] << "\n"; -} -int main() -{ - ios::sync_with_stdio(0); - cin.tie(0); - cout.tie(0); - int t = 1; - // cin >> t; - while (t--) - { - solve(); - } + for (int i = 0; i < m; i++) + cout << ans[i] + 1 << "\n"; return 0; } \ No newline at end of file diff --git "a/\345\271\266\346\237\245\351\233\206.cpp" "b/\345\271\266\346\237\245\351\233\206.cpp" new file mode 100644 index 0000000..d6a15cd --- /dev/null +++ "b/\345\271\266\346\237\245\351\233\206.cpp" @@ -0,0 +1,20 @@ +#include +using namespace std; +vector pre; +void dsu_init(int n) +{ + pre.resize(n); + for (int i = 0; i < n; i++) + pre[i] = i; +} +int dsu_find(int u) +{ + // 路径压缩优化: pre[u] = ... + return pre[u] = pre[u] == u ? u : dsu_find(pre[u]); +} +void dsu_union(int u, int v) +{ + u = dsu_find(u); + v = dsu_find(v); + pre[u] = v; +} \ No newline at end of file From 91b38f8211c5c6b062bfd3731f8b3b7df1f7eaa2 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Sat, 29 Nov 2025 15:33:48 +0800 Subject: [PATCH 21/25] modify code --- ...7\347\224\237\346\210\220\346\240\221.cpp" | 130 ++++++++++++++++++ "\345\200\215\345\242\236LCA.cpp" | 64 +++++++++ 2 files changed, 194 insertions(+) create mode 100644 "\344\270\245\346\240\274\346\254\241\345\260\217\347\224\237\346\210\220\346\240\221.cpp" create mode 100644 "\345\200\215\345\242\236LCA.cpp" diff --git "a/\344\270\245\346\240\274\346\254\241\345\260\217\347\224\237\346\210\220\346\240\221.cpp" "b/\344\270\245\346\240\274\346\254\241\345\260\217\347\224\237\346\210\220\346\240\221.cpp" new file mode 100644 index 0000000..01b51e3 --- /dev/null +++ "b/\344\270\245\346\240\274\346\254\241\345\260\217\347\224\237\346\210\220\346\240\221.cpp" @@ -0,0 +1,130 @@ +#include +using namespace std; +const int DEP = 17; +vector> e; +vector pre; +vector>> g; +vector> f; +vector> st; +vector dep; +vector vis, sel; +bool cmp(tuple a, tuple b) +{ + return get<2>(a) < get<2>(b); +} +void dsu_init(int n) +{ + pre.resize(n); + for (int i = 0; i < n; i++) + pre[i] = i; +} +int dsu_find(int u) +{ + return pre[u] = pre[u] == u ? u : dsu_find(pre[u]); +} +void build(int u, int fa) +{ + vis[u] = true; + dep[u] = dep[fa] + 1; + f[u][0] = fa; + for (int i = 1; i < DEP; i++) + { + f[u][i] = f[f[u][i - 1]][i - 1]; + st[u][i] = max(st[u][i - 1], st[f[u][i - 1]][i - 1]); + } + for (auto [v, w] : g[u]) + if (v != fa) + { + st[v][0] = w; + build(v, u); + } +} +/** + * @brief 求两点路径中最大权值(但小于上界), 采用倍增 + * @param u, v 两点 + * @param w 权值上界 + */ +int get_ans(int u, int v, int w) +{ + if (dep[u] < dep[v]) + swap(u, v); + int ans = -1e9; + for (int i = DEP - 1; i >= 0; i--) + if (dep[f[u][i]] >= dep[v]) + { + if (st[u][i] < w) + ans = max(ans, st[u][i]); + u = f[u][i]; + } + if (u == v) + return ans; + for (int i = DEP - 1; i >= 0; i--) + if (f[u][i] != f[v][i]) + { + if (st[u][i] < w) + ans = max(ans, st[u][i]); + if (st[v][i] < w) + ans = max(ans, st[v][i]); + u = f[u][i]; + v = f[v][i]; + } + if (st[u][0] < w) + ans = max(ans, st[u][0]); + if (st[v][0] < w) + ans = max(ans, st[v][0]); + return ans; +} +/** + * @brief 测试链接: https://www.luogu.com.cn/problem/P4180 + */ +int main() +{ + ios::sync_with_stdio(false); + cin.tie(nullptr); + int n, m; + cin >> n >> m; + n++; + for (int i = 0; i < m; i++) + { + int u, v, w; + cin >> u >> v >> w; + e.push_back({u, v, w}); + } + sort(e.begin(), e.end(), cmp); + dsu_init(n); + g.resize(n); + f.resize(n, vector(DEP)); + st.resize(n, vector(DEP)); + dep.resize(n); + vis.resize(n); + sel.resize(m); + long long sum = 0; + for (int i = 0; i < m; i++) + { + auto [u, v, w] = e[i]; + int fu = dsu_find(u); + int fv = dsu_find(v); + if (fu == fv) + continue; + pre[fu] = fv; + sum += w; + sel[i] = true; + g[u].push_back({v, w}); + g[v].push_back({u, w}); + } + for (int i = 1; i < n; i++) + if (!vis[i]) + build(i, 0); + int diff = 1e9; + for (int i = 0; i < m; i++) + { + if (sel[i]) + continue; + auto [u, v, w] = e[i]; + int td = w - get_ans(u, v, w); + if (td > 0) + diff = min(diff, td); + } + cout << sum + diff << "\n"; + return 0; +} \ No newline at end of file diff --git "a/\345\200\215\345\242\236LCA.cpp" "b/\345\200\215\345\242\236LCA.cpp" new file mode 100644 index 0000000..504eda5 --- /dev/null +++ "b/\345\200\215\345\242\236LCA.cpp" @@ -0,0 +1,64 @@ +#include +using namespace std; +vector> g, f; +vector dep; +void build(int u, int fa) +{ + dep[u] = dep[fa] + 1; + f[u][0] = fa; + for (int i = 1; i < 20; i++) + // 建立多级父子关系, 优化到O(n*logn) + f[u][i] = f[f[u][i - 1]][i - 1]; + for (int v : g[u]) + if (v != fa) + build(v, u); +} +int get_lca(int u, int v) +{ + if (dep[u] < dep[v]) + swap(u, v); + // 先一个跳 + for (int i = 19; i >= 0; --i) + if (dep[f[u][i]] >= dep[v]) + u = f[u][i]; + if (u == v) + return u; + // 再两个跳 + for (int i = 19; i >= 0; --i) + if (f[u][i] != f[v][i]) + { + u = f[u][i]; + v = f[v][i]; + } + return f[u][0]; +} +/** + * @brief 测试链接: https://www.luogu.com.cn/problem/P3379 + */ +int main() +{ + // 本题卡常, 故关闭同步流 + ios::sync_with_stdio(false); + cin.tie(nullptr); + int n, m, s; + cin >> n >> m >> s; + n++; + g.resize(n); + f.resize(n, vector(20)); + dep.resize(n); + for (int i = 0; i < n - 2; i++) + { + int u, v; + cin >> u >> v; + g[u].push_back(v); + g[v].push_back(u); + } + build(s, 0); + for (int i = 0; i < m; i++) + { + int u, v; + cin >> u >> v; + cout << get_lca(u, v) << "\n"; + } + return 0; +} \ No newline at end of file From 258368148a5ebe95111d015e21b9b49953a6e8c4 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Mon, 15 Dec 2025 19:41:47 +0800 Subject: [PATCH 22/25] modify code --- "\347\272\277\346\256\265\346\240\221.cpp" | 91 ++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 "\347\272\277\346\256\265\346\240\221.cpp" diff --git "a/\347\272\277\346\256\265\346\240\221.cpp" "b/\347\272\277\346\256\265\346\240\221.cpp" new file mode 100644 index 0000000..7619089 --- /dev/null +++ "b/\347\272\277\346\256\265\346\240\221.cpp" @@ -0,0 +1,91 @@ +#include +using namespace std; +using ll = long long; +vector tr, tg; +void up(int u) +{ + int ls = u * 2 + 1; + int rs = u * 2 + 2; + tr[u] = tr[ls] + tr[rs]; +} +void down(int l, int r, int u) +{ + if (!tg[u]) + return; + int mid = (l + r) / 2; + int ls = u * 2 + 1; + int rs = u * 2 + 2; + tr[ls] += tg[u] * (mid - l); + tr[rs] += tg[u] * (r - mid); + tg[ls] += tg[u]; + tg[rs] += tg[u]; + tg[u] = 0; +} +void upd(int L, int R, ll x, int l, int r, int u) +{ + if (R <= l || r <= L) + return; + if (L <= l && r <= R) + { + tr[u] += x * (r - l); + tg[u] += x; + return; + } + down(l, r, u); + int mid = (l + r) / 2; + upd(L, R, x, l, mid, u * 2 + 1); + upd(L, R, x, mid, r, u * 2 + 2); + up(u); +} +ll qry(int L, int R, int l, int r, int u) +{ + if (R <= l || r <= L) + return 0; + if (L <= l && r <= R) + return tr[u]; + down(l, r, u); + int mid = (l + r) / 2; + ll ans = 0; + ans += qry(L, R, l, mid, u * 2 + 1); + ans += qry(L, R, mid, r, u * 2 + 2); + return ans; +} +/** + * @brief 链接: https://www.luogu.com.cn/problem/P3372 + */ +int main() +{ + ios::sync_with_stdio(false); + cin.tie(nullptr); + int n, m; + cin >> n >> m; + tr.resize(n * 4); + tg.resize(n * 4); + for (int i = 0; i < n; i++) + { + ll x; + cin >> x; + upd(i, i + 1, x, 0, n, 0); + } + for (int i = 0; i < m; i++) + { + int op; + cin >> op; + if (op == 1) + { + int l, r; + ll x; + cin >> l >> r >> x; + l--; + upd(l, r, x, 0, n, 0); + } + else + { + int l, r; + cin >> l >> r; + l--; + cout << qry(l, r, 0, n, 0) << "\n"; + } + } + return 0; +} \ No newline at end of file From 94f01beeef1db5d0ad3b5274323918ed5ba364d1 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Fri, 19 Dec 2025 01:43:50 +0800 Subject: [PATCH 23/25] modify code --- ...1\347\232\204\347\233\264\345\276\204.cpp" | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 "\346\240\221\347\232\204\347\233\264\345\276\204.cpp" diff --git "a/\346\240\221\347\232\204\347\233\264\345\276\204.cpp" "b/\346\240\221\347\232\204\347\233\264\345\276\204.cpp" new file mode 100644 index 0000000..d915071 --- /dev/null +++ "b/\346\240\221\347\232\204\347\233\264\345\276\204.cpp" @@ -0,0 +1,32 @@ +#include +using namespace std; +vector>> g; // 图的邻接表 +vector vis, // 是否访问,非必需 + son, // 深儿子,深度最大的点在以它为根的子树中 + dis; // 深度 +/// @brief 求以 u 为根的树的最大深度 +/// @param u 树根 +/// @param f 父亲 +/// @return 深度最大的点 +int dfs(int u, int f) +{ + int ans = u; + vis[u] = true; + son[u] = 0; + for (auto [v, w] : g[u]) + { + if (v == f) + continue; + if (!vis[v]) + { + dis[v] = dis[u] + w; + int b = dfs(v, u); + if (dis[ans] < dis[b]) + { + son[u] = v; + ans = b; + } + } + } + return ans; +} \ No newline at end of file From 3539170f0dd635c9292914e3fd2ec818eef8beec Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Tue, 23 Dec 2025 09:38:03 +0800 Subject: [PATCH 24/25] modify code --- "AVL\346\240\221.cpp" | 9 +- "Splay\346\240\221.cpp" | 333 +++++++++++++++++++++++++++++++++ "Splay\346\240\221_doubao.cpp" | 235 +++++++++++++++++++++++ 3 files changed, 571 insertions(+), 6 deletions(-) create mode 100644 "Splay\346\240\221.cpp" create mode 100644 "Splay\346\240\221_doubao.cpp" diff --git "a/AVL\346\240\221.cpp" "b/AVL\346\240\221.cpp" index 9dfa76a..fa2d255 100644 --- "a/AVL\346\240\221.cpp" +++ "b/AVL\346\240\221.cpp" @@ -1,7 +1,6 @@ /** - * @brief AVL树 - * - * @note 节点编号从1开始 + * AVL树 + * 节点编号从1开始 */ #include using namespace std; @@ -194,9 +193,7 @@ int get_post(int u, int x) return get_post(rs[u], x); } /** - * @brief 使用示例 - * - * @note 测试链接: https://www.luogu.com.cn/problem/P3369 + * @brief 测试链接: https://www.luogu.com.cn/problem/P3369 */ int main() { diff --git "a/Splay\346\240\221.cpp" "b/Splay\346\240\221.cpp" new file mode 100644 index 0000000..b61ae3e --- /dev/null +++ "b/Splay\346\240\221.cpp" @@ -0,0 +1,333 @@ +/** + * 伸展树 + * 节点编号从1开始 + */ +#include +using namespace std; + +vector key, cnt, ls, rs, sz; +int tot = 1; + +/** + * @brief 更新节点大小 + */ +void upd(int u) +{ + sz[u] = sz[ls[u]] + sz[rs[u]] + cnt[u]; +} + +/** + * @brief 左旋 + */ +int lrot(int u) +{ + int r = rs[u]; + rs[u] = ls[r]; + ls[r] = u; + upd(u); + upd(r); + return r; +} + +/** + * @brief 右旋 + */ +int rrot(int u) +{ + int l = ls[u]; + ls[u] = rs[l]; + rs[l] = u; + upd(u); + upd(l); + return l; +} + +/** + * @brief 单旋操作(用于最后一步调整) + */ +int splay(int u) +{ + if (ls[ls[u]]) + { // 左左情况 + u = rrot(u); + } + else if (rs[rs[u]]) + { // 右右情况 + u = lrot(u); + } + return u; +} + +/** + * @brief 伸展操作:将包含x的节点旋转到根 + */ +int splay(int u, int x) +{ + if (u == 0) + return 0; + + if (x < key[u]) + { + if (ls[u] == 0) + return u; + + if (x < key[ls[u]]) + { // 左左情况 + ls[ls[u]] = splay(ls[ls[u]], x); + u = rrot(u); // 第一次旋转 + if (ls[u]) + u = rrot(u); // 第二次旋转 + } + else if (x > key[ls[u]]) + { // 左右情况 + rs[ls[u]] = splay(rs[ls[u]], x); + if (rs[ls[u]]) + ls[u] = lrot(ls[u]); + } + + if (ls[u] == 0) + return u; + else + return rrot(u); // 最后一次旋转 + } + else if (x > key[u]) + { + if (rs[u] == 0) + return u; + + if (x > key[rs[u]]) + { // 右右情况 + rs[rs[u]] = splay(rs[rs[u]], x); + u = lrot(u); // 第一次旋转 + if (rs[u]) + u = lrot(u); // 第二次旋转 + } + else if (x < key[rs[u]]) + { // 右左情况 + ls[rs[u]] = splay(ls[rs[u]], x); + if (ls[rs[u]]) + rs[u] = rrot(rs[u]); + } + + if (rs[u] == 0) + return u; + else + return lrot(u); // 最后一次旋转 + } + // x == key[u]时,执行最后一次单旋调整 + return splay(u); +} + +/** + * @brief 插入新节点 + */ +int insert(int u, int x) +{ + if (u == 0) + { + u = tot++; + key[u] = x; + cnt[u] = 1; + sz[u] = 1; + return u; + } + + if (x < key[u]) + { + ls[u] = insert(ls[u], x); + } + else if (x > key[u]) + { + rs[u] = insert(rs[u], x); + } + else + { + cnt[u]++; + } + + upd(u); + return splay(u, x); // 插入后伸展到根 +} + +/** + * @brief 查找最小值节点(用于删除操作) + */ +int find_min(int u) +{ + while (ls[u]) + u = ls[u]; + return u; +} + +/** + * @brief 删除节点 + */ +int remove(int u, int x) +{ + if (u == 0) + return 0; + + u = splay(u, x); // 先将待删除节点伸展到根 + + if (key[u] != x) + return u; // 未找到节点 + + if (cnt[u] > 1) + { + cnt[u]--; + upd(u); + return u; + } + + // 处理子树情况 + int new_root; + if (ls[u] == 0) + { + new_root = rs[u]; + } + else if (rs[u] == 0) + { + new_root = ls[u]; + } + else + { + new_root = find_min(rs[u]); + rs[new_root] = splay(rs[u], key[new_root]); // 伸展右子树最小值到根 + ls[new_root] = ls[u]; + } + + if (new_root != 0) + upd(new_root); + return new_root; +} + +/** + * @brief 获取节点排名(从0开始) + */ +int get_rank(int u, int x) +{ + if (u == 0) + return 0; + if (x > key[u]) + { + return sz[ls[u]] + cnt[u] + get_rank(rs[u], x); + } + else + { + return get_rank(ls[u], x); + } +} + +/** + * @brief 获取指定排名的节点键 + */ +int get_key(int u, int rk) +{ + if (sz[ls[u]] > rk) + { + return get_key(ls[u], rk); + } + else if (sz[ls[u]] + cnt[u] <= rk) + { + return get_key(rs[u], rk - sz[ls[u]] - cnt[u]); + } + else + { + return key[u]; + } +} + +/** + * @brief 获取节点前驱 + */ +int get_pre(int u, int x) +{ + if (u == 0) + return -1e9; + if (key[u] < x) + { + return max(key[u], get_pre(rs[u], x)); + } + else + { + return get_pre(ls[u], x); + } +} + +/** + * @brief 获取节点后继 + */ +int get_post(int u, int x) +{ + if (u == 0) + return 1e9; + if (key[u] > x) + { + return min(key[u], get_post(ls[u], x)); + } + else + { + return get_post(rs[u], x); + } +} + +/** + * @brief 测试链接: https://www.luogu.com.cn/problem/P3369 + */ +int main() +{ + int n; + cin >> n; + // 预留足够空间 + key.resize(n + 2); + cnt.resize(n + 2); + ls.resize(n + 2); + rs.resize(n + 2); + sz.resize(n + 2); + + int root = 0; + for (int i = 0; i < n; i++) + { + int op, x; + cin >> op >> x; + if (op == 1) + { + root = insert(root, x); + } + else if (op == 2) + { + root = remove(root, x); + } + else if (op == 3) + { + // 查询排名前先伸展,确保树结构优化 + if (root != 0) + root = splay(root, x); + cout << get_rank(root, x) + 1 << "\n"; + } + else if (op == 4) + { + cout << get_key(root, x - 1) << "\n"; + // 查询后伸展该节点 + if (root != 0) + root = splay(root, get_key(root, x - 1)); + } + else if (op == 5) + { + int pre = get_pre(root, x); + cout << pre << "\n"; + // 伸展前驱节点 + if (root != 0 && pre != -1e9) + root = splay(root, pre); + } + else if (op == 6) + { + int post = get_post(root, x); + cout << post << "\n"; + // 伸展后继节点 + if (root != 0 && post != 1e9) + root = splay(root, post); + } + } + return 0; +} \ No newline at end of file diff --git "a/Splay\346\240\221_doubao.cpp" "b/Splay\346\240\221_doubao.cpp" new file mode 100644 index 0000000..1f4806d --- /dev/null +++ "b/Splay\346\240\221_doubao.cpp" @@ -0,0 +1,235 @@ +#include +#include +using namespace std; + +const int MAX_SIZE = 1000; // 伸展树最大节点数 + +class ArraySplayTree { +private: + int key[MAX_SIZE]; // 存储节点键值 + int parent[MAX_SIZE]; // 父节点下标,-1表示无父节点 + int left[MAX_SIZE]; // 左孩子下标,-1表示无左孩子 + int right[MAX_SIZE]; // 右孩子下标,-1表示无右孩子 + bool is_left_child[MAX_SIZE];// 标记是否为父节点的左孩子 + int root; // 根节点下标 + int cnt; // 已使用节点数 + + // 左旋操作 + void rotate_left(int x) { + int y = parent[x]; + int T2 = left[x]; + + if (T2 != -1) { + parent[T2] = y; + is_left_child[T2] = (left[y] == x); + } + right[y] = T2; + + parent[x] = parent[y]; + if (parent[y] != -1) { + if (is_left_child[y]) { + left[parent[y]] = x; + } else { + right[parent[y]] = x; + } + is_left_child[x] = is_left_child[y]; + } else { + root = x; + is_left_child[x] = false; + } + + parent[y] = x; + is_left_child[y] = true; + left[x] = y; + } + + // 右旋操作 + void rotate_right(int x) { + int y = parent[x]; + int T2 = right[x]; + + if (T2 != -1) { + parent[T2] = y; + is_left_child[T2] = (left[y] == x); + } + left[y] = T2; + + parent[x] = parent[y]; + if (parent[y] != -1) { + if (is_left_child[y]) { + left[parent[y]] = x; + } else { + right[parent[y]] = x; + } + is_left_child[x] = is_left_child[y]; + } else { + root = x; + is_left_child[x] = false; + } + + parent[y] = x; + is_left_child[y] = false; + right[x] = y; + } + + // 伸展操作:将x移到根 + void splay(int x) { + while (parent[x] != -1) { + int p = parent[x]; + if (parent[p] == -1) { // 单旋 + if (is_left_child[x]) rotate_right(x); + else rotate_left(x); + } else { + int g = parent[p]; + if (is_left_child[p] == is_left_child[x]) { // zig-zig + if (is_left_child[p]) { + rotate_right(p); + rotate_right(x); + } else { + rotate_left(p); + rotate_left(x); + } + } else { // zig-zag + if (is_left_child[x]) { + rotate_right(x); + rotate_left(x); + } else { + rotate_left(x); + rotate_right(x); + } + } + } + } + } + + // 合并两棵树:左树最大值 < 右树最小值 + int merge(int left_tree, int right_tree) { + if (left_tree == -1) return right_tree; + if (right_tree == -1) return left_tree; + + // 找左树的最右节点(最大值) + int max_node = left_tree; + while (right[max_node] != -1) { + max_node = right[max_node]; + } + splay(max_node); // 伸展为左树根 + // 合并右树到 max_node 的右子树 + right[max_node] = right_tree; + parent[right_tree] = max_node; + is_left_child[right_tree] = false; + return max_node; + } + +public: + ArraySplayTree() { + memset(key, 0, sizeof(key)); + memset(parent, -1, sizeof(parent)); + memset(left, -1, sizeof(left)); + memset(right, -1, sizeof(right)); + memset(is_left_child, false, sizeof(is_left_child)); + root = -1; + cnt = 0; + } + + // 插入节点 + void insert(int k) { + if (cnt >= MAX_SIZE) { + cout << "树已满,无法插入!" << endl; + return; + } + int new_node = cnt++; + key[new_node] = k; + + if (root == -1) { + root = new_node; + return; + } + + int curr = root; + int p = -1; + bool is_left = false; + while (curr != -1) { + p = curr; + if (k < key[curr]) { + curr = left[curr]; + is_left = true; + } else { + curr = right[curr]; + is_left = false; + } + } + + parent[new_node] = p; + is_left_child[new_node] = is_left; + if (is_left) left[p] = new_node; + else right[p] = new_node; + + splay(new_node); + } + + // 查找节点,找到返回下标,否则返回-1 + int find(int k) { + int curr = root; + while (curr != -1 && key[curr] != k) { + if (k < key[curr]) curr = left[curr]; + else curr = right[curr]; + } + if (curr != -1) splay(curr); + return curr; + } + + // 删除节点 + bool remove(int k) { + int del_node = find(k); + if (del_node == -1) { + cout << "节点 " << k << " 不存在!" << endl; + return false; + } + // 目标节点已伸展到根 + int left_sub = left[del_node]; + int right_sub = right[del_node]; + + // 断开子树与删除节点的关系 + if (left_sub != -1) parent[left_sub] = -1; + if (right_sub != -1) parent[right_sub] = -1; + + // 合并左右子树作为新根 + root = merge(left_sub, right_sub); + return true; + } + + // 中序遍历 + void inorder(int node) { + if (node == -1) return; + inorder(left[node]); + cout << key[node] << " (left: " << boolalpha << is_left_child[node] << ") "; + inorder(right[node]); + } + + void inorder() { + inorder(root); + cout << endl; + } +}; + +// 测试代码 +int main() { + ArraySplayTree tree; + tree.insert(10); + tree.insert(20); + tree.insert(5); + tree.insert(15); + + cout << "初始中序遍历:"; + tree.inorder(); + + tree.remove(15); + cout << "删除15后遍历:"; + tree.inorder(); + + tree.remove(10); + cout << "删除10后遍历:"; + tree.inorder(); + + return 0; +} \ No newline at end of file From ffd1d2b8db8115f1bcdba2b67f124d8a41072e12 Mon Sep 17 00:00:00 2001 From: gitjip <2672259086@qq.com> Date: Fri, 26 Dec 2025 13:02:25 +0800 Subject: [PATCH 25/25] modify code --- ...5\346\240\221\345\220\210\345\271\266.cpp" | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 "\347\272\277\346\256\265\346\240\221\345\220\210\345\271\266.cpp" diff --git "a/\347\272\277\346\256\265\346\240\221\345\220\210\345\271\266.cpp" "b/\347\272\277\346\256\265\346\240\221\345\220\210\345\271\266.cpp" new file mode 100644 index 0000000..d9d73c0 --- /dev/null +++ "b/\347\272\277\346\256\265\346\240\221\345\220\210\345\271\266.cpp" @@ -0,0 +1,88 @@ +#include +using namespace std; +vector arr, // 需要保留原始数组并操作 + len, // 线段树中该点的最长区间 + llen, // 该点的从左端点开始的最长区间 + rlen; // 该点的从右端点开始的最长区间 +/// @brief 线段树合并,求满足条件的连续最长区间长度 +/// @param l +/// @param r +/// @param u +void up(int l, int r, int u) +{ + int mid = (l + r) / 2; + int ls = u * 2 + 1; + int rs = u * 2 + 2; + len[u] = max(len[ls], len[rs]); + llen[u] = llen[ls]; + rlen[u] = rlen[rs]; + if (arr[mid - 1] != arr[mid]) + { + len[u] = max(len[u], rlen[ls] + llen[rs]); + if (llen[ls] == mid - l) + llen[u] = mid - l + llen[rs]; + if (rlen[rs] == r - mid) + rlen[u] = r - mid + rlen[ls]; + } +} +void build(int l, int r, int u) +{ + if (l + 1 == r) + { + len[u] = llen[u] = rlen[u] = 1; + return; + } + int mid = (l + r) / 2; + build(l, mid, u * 2 + 1); + build(mid, r, u * 2 + 2); + up(l, r, u); +} +void upd(int p, int l, int r, int u) +{ + if (r <= p || p < l) + return; + if (l + 1 == r) + { + arr[p] ^= 1; + return; + } + int mid = (l + r) / 2; + upd(p, l, mid, u * 2 + 1); + upd(p, mid, r, u * 2 + 2); + up(l, r, u); +} +/// @brief 调试,输出线段树每点的值 +/// @param l +/// @param r +/// @param u +void out(int l, int r, int u) +{ + cout << l << " " << r - 1 << ":" << len[u] << " " << llen[u] << " " << rlen[u] << "\n"; + if (l + 1 == r) + return; + int mid = (l + r) / 2; + out(l, mid, u * 2 + 1); + out(mid, r, u * 2 + 2); +} +/// @brief 测试链接:https://www.luogu.com.cn/problem/P6492 +/// @return +int main() +{ + int n, q; + cin >> n >> q; + arr.resize(n); + len.resize(n * 4); + llen.resize(n * 4); + rlen.resize(n * 4); + build(0, n, 0); + while (q--) + { + int x; + cin >> x; + x--; + upd(x, 0, n, 0); + cout << len[0] << "\n"; + // out(0, n, 0); + } + return 0; +} \ No newline at end of file