#include #include #include #include /** * 2055. Plates Between Candles * There is a long table with a line of plates and candles arranged on top of it. You are given a 0-indexed string s consisting of characters '*' and '|' only, where a '*' represents a plate and a '|' represents a candle. * You are also given a 0-indexed 2D integer array queries where queries[i] = [lefti, righti] denotes the substring s[lefti...righti] (inclusive). For each query, you need to find the number of plates between candles that are in the substring. A plate is considered between candles if there is at least one candle to its left and at least one candle to its right in the substring. * For example, s = "||**||**|*", and a query [3, 8] denotes the substring "*||**|". The number of plates between candles in this substring is 2, as each of the two plates has at least one candle in the substring to its left and right. * Return an integer array answer where answer[i] is the answer to the ith query. */ class Solution { private: inline static constexpr int HIGH(int x, int y) { const int r = 32 - __builtin_clz(x ^ y); return ((((x | y) >> r) + 1) << r) - 1; } inline static constexpr int MID(int x, int y) { return (x | y) & ~((1 << 31 - __builtin_clz(x ^ y)) - 1); } inline static constexpr int LOW(int x, int y) { const int r = 32 - __builtin_clz(x ^ y); return (x | y) >> r << r; } inline static constexpr int MSB(int x) { return 31 - __builtin_clz(x); } static int dp(int L, int R, const std::string& s, std::vector>& ans) { if (L == R) return int(s[L] == '*'); if (L == (R ^ 1)) return ans[1][L >> 1] = (s[L] == '*') + (s[R] == '*'); if (L == LOW(L, R) && R == HIGH(L, R)) { const int x = 1 + MSB(L ^ R), idx = L >> x; auto& m = ans[x]; if (m.count(idx)) return m[idx]; else return m[idx] = dp(L, L | ((1 << (x - 1)) - 1), s, ans) + dp(L | (1 << (x - 1)), R, s, ans); } else { int M = MID(L, R); return dp(L, M - 1, s, ans) + dp(M, R, s, ans); } } public: static std::vector platesBetweenCandles(const std::string& s, const std::vector>& queries) { int n = s.length(); std::vector> ans(32 - __builtin_clz(n)); std::vector ret, positions; ret.reserve(queries.size()); for (int i = 0; i < n; ++i) if (s[i] == '|') positions.push_back(i); if (positions.empty()) return std::vector(queries.size()); for (auto i : queries) { auto begin = std::lower_bound(positions.begin(), positions.end(), i[0]); auto end = std::lower_bound(positions.begin(), positions.end(), i[1]); if (begin == end) { ret.push_back(0); continue; } if (end == positions.end() || *end > i[1]) --end; if (begin == positions.end() || *begin >= *end) ret.push_back(0); else ret.push_back(dp(*begin, *end, s, ans)); } return ret; } }; int main() { auto ret = Solution::platesBetweenCandles("*|*|||", {{0, 0}, {1, 3}}); for (int i : ret) std::cout << i << ' '; return 0; }