diff --git a/README.md b/README.md index 044872f1..f6c6b521 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ This project contains my competitive programming library, examples, and solution * [Disjoint Set Union](/lib/cpalgo/ds/README.md#Disjoint-Set-Union) * [Binary Indexed Tree](/lib/cpalgo/ds/README.md#Binary-Indexed-Tree) -* [Minimum Queue](/lib/cpalgo/ds/README.md#Minimum-Queue) +* [MinMax Queue](/lib/cpalgo/ds/README.md#MinMax-Queue) * [MinMax Stack](/lib/cpalgo/ds/README.md#MinMax-Stack) * [Randomized Heap](/lib/cpalgo/ds/README.md#Randomized-Heap) * [Segment Tree](/lib/cpalgo/ds/README.md#Segment-Tree) diff --git a/aoj/DSL/DSL3D/main_minimum-queue.cpp b/aoj/DSL/DSL3D/main_minimum-queue.cpp index a618531f..1ffa1bae 100644 --- a/aoj/DSL/DSL3D/main_minimum-queue.cpp +++ b/aoj/DSL/DSL3D/main_minimum-queue.cpp @@ -56,58 +56,71 @@ class MinMaxStack { }; template > -class MinimumQueue { +class MinMaxQueue { private: - MinMaxStack Sp, Sr; + MinMaxStack in_stack, out_stack; Less less; public: // Time: O(1) bool empty() const { - return Sp.empty() && Sr.empty(); + return in_stack.empty() && out_stack.empty(); } // Time: O(1) size_t size() const { - return Sp.size() + Sr.size(); + return in_stack.size() + out_stack.size(); } // Time: O(1) void push(T const& value) { - Sp.push(value); + in_stack.push(value); } // Time: O(N), amortized O(1) void pop() { - if (Sr.empty()) { - while (!Sp.empty()) { - auto value = Sp.top(); - Sp.pop(); - Sr.push(value); + if (out_stack.empty()) { + while (!in_stack.empty()) { + auto value = in_stack.top(); + in_stack.pop(); + out_stack.push(value); } } - Sr.pop(); + out_stack.pop(); } // Time: O(1) T front() const { - if (Sr.empty()) { - return Sp.bottom(); + if (out_stack.empty()) { + return in_stack.bottom(); } - return Sr.top(); + return out_stack.top(); } // Time: O(1) T back() const { - if (!Sp.empty()) { - return Sp.top(); + if (!in_stack.empty()) { + return in_stack.top(); } - return Sr.bottom(); + return out_stack.bottom(); } // Time: O(1) T minimum() const { - if (Sp.empty() || Sr.empty()) { - return Sp.empty() ? Sr.minimum() : Sp.minimum(); + if (in_stack.empty()) { + return out_stack.minimum(); + } else if (out_stack.empty()) { + return in_stack.minimum(); } else { - auto m1 = Sp.minimum(), m2 = Sr.minimum(); + auto m1 = in_stack.minimum(), m2 = out_stack.minimum(); return less(m1, m2) ? m1 : m2; } } + // Time: O(1) + T maximum() const { + if (in_stack.empty()) { + return out_stack.maximum(); + } else if (out_stack.empty()) { + return in_stack.maximum(); + } else { + auto m1 = in_stack.maximum(), m2 = out_stack.maximum(); + return less(m1, m2) ? m2 : m1; + } + } }; using namespace std; @@ -123,7 +136,7 @@ int main() { cin >> array[i]; } - MinimumQueue Q; + MinMaxQueue Q; for (int i = 0; i < L; ++i) { Q.push(array[i]); } diff --git a/lib/cpalgo/ds/README.md b/lib/cpalgo/ds/README.md index fefd28c8..f46987dc 100644 --- a/lib/cpalgo/ds/README.md +++ b/lib/cpalgo/ds/README.md @@ -23,8 +23,9 @@ Binary Indexed Tree (Fenwick Tree) is a data structure. ### References in Japanese - [Binary Indexed Tree のはなし](http://hos.ac/slides/20140319_bit.pdf) -## Minimum Queue -🚧WIP +## MinMax Queue +A data structure that allows to store and retrieve elements in a first-in-first-out (FIFO) fashion. +This data structure also allows to retrieval of the minimum and maximum value efficiently. ## MinMax Stack A data structure that allows to store and retrieve elements in a last-in-first-out (LIFO) fashion. diff --git a/lib/cpalgo/ds/minimum_queue.hpp b/lib/cpalgo/ds/minimum_queue.hpp deleted file mode 100644 index 6d9e02fc..00000000 --- a/lib/cpalgo/ds/minimum_queue.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#include "minmax_stack.hpp" - - -// MinimumQueue -// -// Space: O(N) -// -// Verified -// - https://onlinejudge.u-aizu.ac.jp/problems/DSL_3_D -// -template > -class MinimumQueue { -private: - MinMaxStack Sp, Sr; - Less less; - -public: - // Time: O(1) - bool empty() const { - return Sp.empty() && Sr.empty(); - } - // Time: O(1) - size_t size() const { - return Sp.size() + Sr.size(); - } - // Time: O(1) - void push(T const& value) { - Sp.push(value); - } - // Time: O(N), amortized O(1) - void pop() { - if (Sr.empty()) { - while (!Sp.empty()) { - auto value = Sp.top(); - Sp.pop(); - Sr.push(value); - } - } - Sr.pop(); - } - // Time: O(1) - T front() const { - if (Sr.empty()) { - return Sp.bottom(); - } - return Sr.top(); - } - // Time: O(1) - T back() const { - if (!Sp.empty()) { - return Sp.top(); - } - return Sr.bottom(); - } - // Time: O(1) - T minimum() const { - if (Sp.empty() || Sr.empty()) { - return Sp.empty() ? Sr.minimum() : Sp.minimum(); - } else { - auto m1 = Sp.minimum(), m2 = Sr.minimum(); - return less(m1, m2) ? m1 : m2; - } - } -}; \ No newline at end of file diff --git a/lib/cpalgo/ds/minmax_queue.hpp b/lib/cpalgo/ds/minmax_queue.hpp new file mode 100644 index 00000000..4d9cc08d --- /dev/null +++ b/lib/cpalgo/ds/minmax_queue.hpp @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include +#include "minmax_stack.hpp" + + +// MinMaxQueue +// +// Space: O(N) +// +// Verified +// - https://onlinejudge.u-aizu.ac.jp/problems/DSL_3_D +// +template > +class MinMaxQueue { +private: + MinMaxStack in_stack, out_stack; + Less less; + +public: + // Time: O(1) + bool empty() const { + return in_stack.empty() && out_stack.empty(); + } + // Time: O(1) + size_t size() const { + return in_stack.size() + out_stack.size(); + } + // Time: O(1) + void push(T const& value) { + in_stack.push(value); + } + // Time: O(N), amortized O(1) + void pop() { + if (out_stack.empty()) { + while (!in_stack.empty()) { + auto value = in_stack.top(); + in_stack.pop(); + out_stack.push(value); + } + } + out_stack.pop(); + } + // Time: O(1) + T front() const { + if (out_stack.empty()) { + return in_stack.bottom(); + } + return out_stack.top(); + } + // Time: O(1) + T back() const { + if (!in_stack.empty()) { + return in_stack.top(); + } + return out_stack.bottom(); + } + // Time: O(1) + T minimum() const { + if (in_stack.empty()) { + return out_stack.minimum(); + } else if (out_stack.empty()) { + return in_stack.minimum(); + } else { + auto m1 = in_stack.minimum(), m2 = out_stack.minimum(); + return less(m1, m2) ? m1 : m2; + } + } + // Time: O(1) + T maximum() const { + if (in_stack.empty()) { + return out_stack.maximum(); + } else if (out_stack.empty()) { + return in_stack.maximum(); + } else { + auto m1 = in_stack.maximum(), m2 = out_stack.maximum(); + return less(m1, m2) ? m2 : m1; + } + } +}; \ No newline at end of file diff --git a/lib/cpalgo/ds/tests/minimum_queue_test.cpp b/lib/cpalgo/ds/tests/minmax_queue_test.cpp similarity index 67% rename from lib/cpalgo/ds/tests/minimum_queue_test.cpp rename to lib/cpalgo/ds/tests/minmax_queue_test.cpp index 5b0db992..9f4f3c74 100644 --- a/lib/cpalgo/ds/tests/minimum_queue_test.cpp +++ b/lib/cpalgo/ds/tests/minmax_queue_test.cpp @@ -1,21 +1,22 @@ #include #include "gtest/gtest.h" -#include "cpalgo/ds/minimum_queue.hpp" +#include "cpalgo/ds/minmax_queue.hpp" -TEST(MinimumQueueTest, IsEmptyInitially) { - MinimumQueue q; +TEST(MinMaxQueueTest, IsEmptyInitially) { + MinMaxQueue q; EXPECT_TRUE(q.empty()); EXPECT_EQ(0ULL, q.size()); } -TEST(MinimumQueueTest, ShouldPushItems) { - MinimumQueue q; +TEST(MinMaxQueueTest, ShouldPushItems) { + MinMaxQueue q; q.push(2); EXPECT_FALSE(q.empty()); EXPECT_EQ(1ULL, q.size()); EXPECT_EQ(2, q.minimum()); + EXPECT_EQ(2, q.maximum()); EXPECT_EQ(2, q.front()); EXPECT_EQ(2, q.back()); @@ -23,6 +24,7 @@ TEST(MinimumQueueTest, ShouldPushItems) { EXPECT_FALSE(q.empty()); EXPECT_EQ(2ULL, q.size()); EXPECT_EQ(1, q.minimum()); + EXPECT_EQ(2, q.maximum()); EXPECT_EQ(2, q.front()); EXPECT_EQ(1, q.back()); @@ -30,43 +32,47 @@ TEST(MinimumQueueTest, ShouldPushItems) { EXPECT_FALSE(q.empty()); EXPECT_EQ(3ULL, q.size()); EXPECT_EQ(1, q.minimum()); + EXPECT_EQ(3, q.maximum()); EXPECT_EQ(2, q.front()); EXPECT_EQ(3, q.back()); } -TEST(MinimumQueueTest, ShouldPopItems) { - MinimumQueue q; +TEST(MinMaxQueueTest, ShouldPopItems) { + MinMaxQueue q; - q.push(2); - q.push(1); q.push(3); + q.push(1); + q.push(2); EXPECT_FALSE(q.empty()); EXPECT_EQ(3ULL, q.size()); EXPECT_EQ(1, q.minimum()); - EXPECT_EQ(2, q.front()); - EXPECT_EQ(3, q.back()); + EXPECT_EQ(3, q.maximum()); + EXPECT_EQ(3, q.front()); + EXPECT_EQ(2, q.back()); q.pop(); EXPECT_FALSE(q.empty()); EXPECT_EQ(2ULL, q.size()); EXPECT_EQ(1, q.minimum()); + EXPECT_EQ(2, q.maximum()); EXPECT_EQ(1, q.front()); - EXPECT_EQ(3, q.back()); + EXPECT_EQ(2, q.back()); q.pop(); EXPECT_FALSE(q.empty()); EXPECT_EQ(1ULL, q.size()); - EXPECT_EQ(3, q.minimum()); - EXPECT_EQ(3, q.front()); - EXPECT_EQ(3, q.back()); + EXPECT_EQ(2, q.minimum()); + EXPECT_EQ(2, q.maximum()); + EXPECT_EQ(2, q.front()); + EXPECT_EQ(2, q.back()); q.pop(); EXPECT_TRUE(q.empty()); EXPECT_EQ(0ULL, q.size()); } -TEST(MinimumQueueTest, ShouldPushAndPopItems) { - MinimumQueue q; +TEST(MinMaxQueueTest, ShouldPushAndPopItems) { + MinMaxQueue q; q.push(2); q.pop(); @@ -76,6 +82,7 @@ TEST(MinimumQueueTest, ShouldPushAndPopItems) { EXPECT_FALSE(q.empty()); EXPECT_EQ(2ULL, q.size()); EXPECT_EQ(1, q.minimum()); + EXPECT_EQ(3, q.maximum()); EXPECT_EQ(1, q.front()); EXPECT_EQ(3, q.back()); @@ -86,25 +93,29 @@ TEST(MinimumQueueTest, ShouldPushAndPopItems) { EXPECT_FALSE(q.empty()); EXPECT_EQ(3ULL, q.size()); EXPECT_EQ(0, q.minimum()); + EXPECT_EQ(4, q.maximum()); EXPECT_EQ(3, q.front()); EXPECT_EQ(4, q.back()); } -TEST(MinimumQueueTest, ShouldUseCustomComparator) { - MinimumQueue> q; +TEST(MinMaxQueueTest, ShouldUseCustomComparator) { + MinMaxQueue> q; q.push(2); EXPECT_EQ(2, q.minimum()); + EXPECT_EQ(2, q.maximum()); EXPECT_EQ(2, q.front()); EXPECT_EQ(2, q.back()); q.push(3); EXPECT_EQ(3, q.minimum()); + EXPECT_EQ(2, q.maximum()); EXPECT_EQ(2, q.front()); EXPECT_EQ(3, q.back()); q.push(1); EXPECT_EQ(3, q.minimum()); + EXPECT_EQ(1, q.maximum()); EXPECT_EQ(2, q.front()); EXPECT_EQ(1, q.back()); } diff --git a/lib/main/ds/BUILD b/lib/main/ds/BUILD index 6f475e76..d0eb20e8 100644 --- a/lib/main/ds/BUILD +++ b/lib/main/ds/BUILD @@ -31,8 +31,8 @@ cc_binary( ) cc_binary( - name = "minimum-queue", - srcs = ["main-minimum-queue.cpp"], + name = "minmax-queue", + srcs = ["main-minmax-queue.cpp"], copts = COPTS, deps = DEPS, ) diff --git a/lib/main/ds/main-minimum-queue.cpp b/lib/main/ds/main-minmax-queue.cpp similarity index 52% rename from lib/main/ds/main-minimum-queue.cpp rename to lib/main/ds/main-minmax-queue.cpp index 15ea2daf..27a686f1 100644 --- a/lib/main/ds/main-minimum-queue.cpp +++ b/lib/main/ds/main-minmax-queue.cpp @@ -1,39 +1,44 @@ #include #include "template/template-main.hpp" -#include "cpalgo/ds/minimum_queue.hpp" +#include "cpalgo/ds/minmax_queue.hpp" using namespace std; -MinimumQueue minqueue; +MinMaxQueue minmax_queue; void action_init() { - minqueue = MinimumQueue(); + minmax_queue = MinMaxQueue(); } void action_push() { int value; cin >> value; - minqueue.push(value); + minmax_queue.push(value); } void action_pop() { - if (minqueue.empty()) return; - minqueue.pop(); + if (minmax_queue.empty()) return; + minmax_queue.pop(); } void action_front() { - if (minqueue.empty()) return; - cout << minqueue.front() << endl; + if (minmax_queue.empty()) return; + cout << minmax_queue.front() << endl; } void action_back() { - if (minqueue.empty()) return; - cout << minqueue.back() << endl; + if (minmax_queue.empty()) return; + cout << minmax_queue.back() << endl; } void action_minimum() { - if (minqueue.empty()) return; - cout << minqueue.minimum() << endl; + if (minmax_queue.empty()) return; + cout << minmax_queue.minimum() << endl; +} + +void action_maximum() { + if (minmax_queue.empty()) return; + cout << minmax_queue.maximum() << endl; } void setup(string& header, map& commands) { @@ -44,4 +49,5 @@ void setup(string& header, map& commands) { commands["front"] = { "front", action_front }; commands["back"] = { "back", action_back }; commands["min"] = { "min", action_minimum }; + commands["max"] = { "max", action_maximum }; } \ No newline at end of file