diff --git a/2201/220123-CN.cpp b/2201/220123-CN.cpp new file mode 100644 index 0000000..8ba7782 --- /dev/null +++ b/2201/220123-CN.cpp @@ -0,0 +1,204 @@ +#include +#include +#include +#include +#include +#include +#include + +class StockPrice { +private: + std::unordered_map m; + std::multiset min; + int currentTS = -1, currentPrice = -1; +public: + StockPrice() = default; + + void update(int timestamp, int price) { + if (timestamp >= currentTS) { + currentTS = timestamp; + currentPrice = price; + } + if (m.count(timestamp)) { + min.erase(min.find(m[timestamp])); + } + m[timestamp] = price; + min.insert(price); + } + + int current() const { + return currentPrice; + } + + int maximum() const { + return *min.rbegin(); + } + + int minimum() const { + return *min.begin(); + } +}; + +class StockPriceHashMap { +private: + int currentTS = -1, currentPrice = -1; + bool updatedMax = false, updatedMin = false; + int max = -1, min = 0x7FFFFFFF, maxTS = -1, minTS = -1; + std::unordered_map m; +public: + StockPriceHashMap() = default; + + void update(int timestamp, int price) { + if (timestamp >= currentTS) { + currentTS = timestamp; + currentPrice = price; + } + m[timestamp] = price; + if (price >= max || maxTS == timestamp) + updatedMax = true; + if (price <= min || minTS == timestamp) + updatedMin = true; + } + + int current() const { + return currentPrice; + } + + int maximum() { + if (!updatedMax) + return max; + updatedMax = false; + max = -1; + for (const auto& i : m) { + if (i.second > max) { + maxTS = i.first; + max = i.second; + } + } + return max; + } + + int minimum() { + if (!updatedMin) + return min; + updatedMin = false; + min = 0x7FFFFFFF; + for (const auto& i : m) { + if (i.second < min) { + minTS = i.first; + min = i.second; + } + } + return min; + } +}; + +class StockPriceHeap { + std::vector> maxHeap, minHeap; + int currentTS = -1, currentPrice = -1; + std::unordered_set involvedTS; + + static constexpr inline int father(int n) { + return ((n + 1) >> 1) - 1; + } + + static constexpr inline int LChild(int n) { + return ((n + 1) << 1) - 1; + } + + static constexpr inline int RChild(int n) { + return (n + 1) << 1; + } + +public: + StockPriceHeap() = default; + + void update(int timestamp, int price) { + if (timestamp >= currentTS) { + currentTS = timestamp; + currentPrice = price; + } + + // Search in minHeap + auto f = [timestamp, price, this](std::vector>& heap, auto cmp) { + int n = heap.size(), pos = n; + if (!this->involvedTS.count(timestamp)) { + // insert into heap; + heap.emplace_back(timestamp, price); + } else { + for (int i = 0; i < n; ++i) { + if (heap[i].first == timestamp) { + if (heap[i].second == price) { + // Found not changed, return immediately + return; + } + heap[i].second = price; + pos = i; + break; + } + } + } + // always treat heap as a maximum heap + // std::make_heap(heap.begin(), heap.end(), cmp); + while (pos && cmp(heap[father(pos)], heap[pos])) { // swap with father + std::swap(heap[pos], heap[father(pos)]); + pos = father(pos); + } + while (true) { // swap with children + int LR = 0; + if (LChild(pos) < n && cmp(heap[pos], heap[LChild(pos)])) + LR = -1; + if (RChild(pos) < n && cmp(LR ? heap[LChild(pos)] : heap[pos], heap[RChild(pos)])) + LR = 1; + if (!LR) + break; + std::swap(heap[pos], LR == 1 ? heap[RChild(pos)] : heap[LChild(pos)]); + pos = LR == 1 ? RChild(pos) : LChild(pos); + } + }; + + f(minHeap, [](const std::pair& x, const std::pair& y) { return x.second > y.second; }); + f(maxHeap, [](const std::pair& x, const std::pair& y) { return x.second < y.second; }); + involvedTS.insert(timestamp); + } + + int current() const { + return currentPrice; + } + + int maximum() const { + return maxHeap[0].second; + } + + int minimum() const { + return minHeap[0].second; + } +}; + +int main() { + StockPrice solver; + /* + solver.update(1, 10); + solver.update(2, 5); + std::cout << "Current = " << solver.current() << std::endl; + std::cout << "Maximum = " << solver.maximum() << std::endl; + solver.update(1, 3); + std::cout << "Maximum = " << solver.maximum() << std::endl; + solver.update(4, 2); + std::cout << "Minimum = " << solver.minimum() << std::endl; + */ + + auto begin = std::chrono::high_resolution_clock::now(); + for (int i = 1; i <= 20000; ++i) { + solver.update(i, i); + } + for (int i = 1; i <= 10000; ++i) { + solver.update(i << 1, 1000000000); + solver.maximum(); + solver.update((i << 1) + 1, 1000000000); + solver.minimum(); + } + auto end = std::chrono::high_resolution_clock::now(); + std::cout << "Time elapsed: " << std::chrono::duration_cast(end - begin).count() << " ms\n"; + return 0; +} diff --git a/2201/CMakeLists.txt b/2201/CMakeLists.txt index afb2ca4..f6bfbfa 100644 --- a/2201/CMakeLists.txt +++ b/2201/CMakeLists.txt @@ -3,4 +3,4 @@ PROJECT(2201) SET(CMAKE_CXX_STANDARD 23) -ADD_EXECUTABLE(2201 220122.cpp) +ADD_EXECUTABLE(2201 220123-CN.cpp)