From 99171c06fbc5dc8411df52ca3387b40df3126087 Mon Sep 17 00:00:00 2001 From: Macesuted Date: Thu, 24 Oct 2024 20:26:11 +0800 Subject: [PATCH] QOJ: The 2022 ICPC Asia Hong Kong Regional Contest --- .vscode/tasks.json | 2 - QOJ/5459.cpp | 83 ++++++++++++++++++++++++++ QOJ/5462.cpp | 30 ++++++++++ templates/Data Structure.md | 116 +++++++++++++++++++++++++++++++++++- 4 files changed, 227 insertions(+), 4 deletions(-) create mode 100644 QOJ/5459.cpp create mode 100644 QOJ/5462.cpp diff --git a/.vscode/tasks.json b/.vscode/tasks.json index e9fe8f6..6d29e54 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -12,7 +12,6 @@ "'${fileBasename}'", "-o", "'${fileBasenameNoExtension}.exe'", - "-std=c++20", "-Wall", "-Wextra", "-O2", @@ -72,7 +71,6 @@ "-o", "'${fileBasenameNoExtension}.exe'", "-glldb", - "-std=c++20", "-Wall", "-Wextra", "-O2", diff --git a/QOJ/5459.cpp b/QOJ/5459.cpp new file mode 100644 index 0000000..716b01f --- /dev/null +++ b/QOJ/5459.cpp @@ -0,0 +1,83 @@ +/** + * @file 5459.cpp + * @author Macesuted (i@macesuted.moe) + * @date 2024-10-24 + * + * @copyright Copyright (c) 2024 + * + */ + +#include +using namespace std; + +#define endl '\n' + +#define maxn 1000005 + +class SegmentTree { + private: + int lim[maxn << 2], ans[maxn << 2], n; + + void pushUp(int p, int l, int r) { return ans[p] = (lim[p] ? 0 : (l == r ? 1 : ans[p << 1] + ans[p << 1 | 1])), void(); } + + void build(int p, int l, int r) { + if (l == r) return lim[p] = 0, ans[p] = 1, void(); + int mid = (l + r) >> 1; + build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r); + return pushUp(p, l, r); + } + void update(int p, int l, int r, int ql, int qr, int delt) { + if (ql <= l && r <= qr) return lim[p] += delt, pushUp(p, l, r); + int mid = (l + r) >> 1; + if (ql <= mid) update(p << 1, l, mid, ql, qr, delt); + if (mid < qr) update(p << 1 | 1, mid + 1, r, ql, qr, delt); + return pushUp(p, l, r); + } + int query(int p, int l, int r, int ql, int qr) { + if (lim[p]) return 0; + if (ql <= l && r <= qr) return ans[p]; + int mid = (l + r) >> 1; + if (qr <= mid) return query(p << 1, l, mid, ql, qr); + if (ql > mid) return query(p << 1 | 1, mid + 1, r, ql, qr); + return query(p << 1, l, mid, ql, qr) + query(p << 1 | 1, mid + 1, r, ql, qr); + } + + public: + void resize(int _n) { return n = _n, void(); } + void build(void) { return build(1, 1, n); } + void update(int l, int r, int delt) { return update(1, 1, n, l, r, delt); } + int query(int l, int r) { return query(1, 1, n, l, r); } +}; + +SegmentTree SGT; +int a[maxn]; +vector pos[maxn]; + +void solve(void) { + int n, k; + cin >> n >> k, SGT.resize(n), SGT.build(); + for (int i = 1; i <= n; i++) cin >> a[i], pos[a[i]].push_back(i); + + for (int i = 1; i <= 1e6; i++) { + pos[i].push_back(n + 1); + if (k < (int)pos[i].size()) SGT.update(pos[i][k - 1], pos[i][k] - 1, +1); + } + int64_t ans = 0; + for (int i = 1; i <= n; i++) { + ans += SGT.query(i, n); + int p = lower_bound(pos[a[i]].begin(), pos[a[i]].end(), i) - pos[a[i]].begin(); + if (p + k < (int)pos[a[i]].size()) SGT.update(pos[a[i]][p + k - 1], pos[a[i]][p + k] - 1, -1); + if (p + k + 1 < (int)pos[a[i]].size()) SGT.update(pos[a[i]][p + k], pos[a[i]][p + k + 1] - 1, +1); + } + cout << ans << endl; + return; +} + +int main() { + ios::sync_with_stdio(false), cin.tie(nullptr); + + int _ = 1; + while (_--) solve(); + + return 0; +} diff --git a/QOJ/5462.cpp b/QOJ/5462.cpp new file mode 100644 index 0000000..fae588d --- /dev/null +++ b/QOJ/5462.cpp @@ -0,0 +1,30 @@ +/** + * @file 5462.cpp + * @author Macesuted (i@macesuted.moe) + * @date 2024-10-24 + * + * @copyright Copyright (c) 2024 + * + */ + +#include +using namespace std; + +#define endl '\n' + +void solve(void) { + int l, r, b, k; + cin >> l >> r >> b >> k; + int64_t range = (l / b + (l % b > 0)) * b; + cout << k * range << endl; + return; +} + +int main() { + ios::sync_with_stdio(false), cin.tie(nullptr); + + int _ = 1; + while (_--) solve(); + + return 0; +} diff --git a/templates/Data Structure.md b/templates/Data Structure.md index 7887edb..df6b09e 100644 --- a/templates/Data Structure.md +++ b/templates/Data Structure.md @@ -268,14 +268,14 @@ class FhqTreap { merge(root, root, tp), merge(root, root, tr); return ans; } - int pre(int x) { + int getPrev(int x) { Node *tr = nullptr, *tp = nullptr; splitV(root, root, tr, x), splitS(root, root, tp, getSiz(root) - 1); int ans = tp->val; merge(root, root, tp), merge(root, root, tr); return ans; } - int suc(int x) { + int getNext(int x) { Node *tr = nullptr, *tp = nullptr; splitV(root, root, tr, x + 1), splitS(tr, tp, tr, 1); int ans = tp->val; @@ -285,6 +285,118 @@ class FhqTreap { }; ``` +## Splay Tree + +```cpp +class Splay { + private: + struct Node { + Node *fa, *child[2]; + int val, cnt, siz; + Node(int _v) { fa = child[0] = child[1] = nullptr, val = _v, cnt = siz = 1; } + }; + + Node *root; + + bool getChild(Node *p) { return p->fa->child[1] == p; } + int getSiz(Node *p) { return p ? p->siz : 0; } + void pushUp(Node *p) { return p->siz = getSiz(p->child[0]) + getSiz(p->child[1]) + p->cnt, void(); } + void rotate(Node *p) { + Node *f = p->fa, *g = f->fa; + bool d = getChild(p); + + if (g) g->child[getChild(f)] = p; + p->fa = g; + + f->child[d] = p->child[!d]; + if (p->child[!d]) p->child[!d]->fa = f; + + p->child[!d] = f, f->fa = p; + return pushUp(f), pushUp(p); + } + void splay(Node *p, Node *tar = nullptr) { + if (!p) return; + for (Node *f = p->fa; f != tar; rotate(p), f = p->fa) + if (f->fa != tar) rotate(getChild(p) == getChild(f) ? f : p); + if (!tar) root = p; + return; + } + + void print(Node *p) { + if (!p) return; + print(p->child[0]); + cout << '(' << p->val << ',' << p->cnt << ')'; + print(p->child[1]); + return; + } + + public: + Splay(void) { root = nullptr; } + + bool insert(int v) { + if (!root) return root = new Node(v), true; + + Node *f = nullptr; + for (Node *p = root; p; f = p, p = p->child[p->val < v]) + if (p->val == v) return p->cnt++, splay(p), false; + + Node *x = new Node(v); + f->child[f->val < v] = x, x->fa = f; + return splay(x), true; + } + bool erase(int v) { + Node *f = nullptr, *x = nullptr; + for (Node *p = root; p && !x; f = p, p = p->child[p->val < v]) + if (p->val == v) x = p; + + if (!x) return splay(f), false; + splay(x); + + if (--x->cnt) return true; + if (!x->child[0] && !x->child[1]) return root = nullptr, delete x, true; + if (!x->child[0]) return (root = x->child[1])->fa = nullptr, delete x, true; + if (!x->child[1]) return (root = x->child[0])->fa = nullptr, delete x, true; + + getPrev(x->val); + root->child[1] = x->child[1], x->child[1]->fa = root, pushUp(root); + return delete x, true; + } + int queryRank(int v) { + int ans = 0; + Node *f = nullptr; + for (Node *p = root; p; f = p, p = p->child[p->val < v]) + if (p->val < v) ans += getSiz(p->child[0]) + p->cnt; + return splay(f), ans + 1; + } + Node *getRank(int v) { + Node *f = nullptr; + for (Node *p = root; p;) { + f = p; + if (v <= getSiz(p->child[0])) + p = p->child[0]; + else if (v <= getSiz(p->child[0]) + p->cnt) + return splay(p), p; + else + v -= getSiz(p->child[0]) + p->cnt, p = p->child[1]; + } + return splay(f), nullptr; + } + Node *getPrev(int v) { + Node *f = nullptr, *x = nullptr; + for (Node *p = root; p; f = p, p = p->child[p->val < v]) + if (p->val < v) x = p; + return splay(f), x; + } + Node *getNext(int v) { + Node *f = nullptr, *x = nullptr; + for (Node *p = root; p; f = p, p = p->child[p->val <= v]) + if (p->val > v) x = p; + return splay(f), x; + } + void print(void) { return cout << '[', print(root), cout << ']' << endl, void(); } +}; +``` + ## Leftist Heap (Persistent) ```cpp