- Choose the invariant that makes a window valid or useful.
- Advance the right boundary and add the new element.
- Move the left boundary only as needed while maintaining the invariant and updating the answer.
Code notes
- 98 lines of C++ from the credited upstream file 2818.cpp.
- The implementation visibly relies on sequence storage, hash lookup.
- 11 loop blocks detected.
Complexity
Confirm that neither pointer moves backwards; if so, the scan is usually linear apart from the window’s data-structure operations.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Solution {2 public:3 int maximumScore(vector<int>& nums, int k) {4 const int n = nums.size();5 const int mx = ranges::max(nums);6 const vector<int> minPrimeFactors = sieveEratosthenes(mx + 1);7 const vector<int> primeScores = getPrimeScores(nums, minPrimeFactors);8 int ans = 1;9 10 11 vector<int> left(n, -1);12 13 14 vector<int> right(n, n);15 stack<int> stack;16 17 18 19 for (int i = n - 1; i >= 0; --i) {20 while (!stack.empty() && primeScores[stack.top()] <= primeScores[i])21 left[stack.top()] = i, stack.pop();22 stack.push(i);23 }24 25 stack = std::stack<int>();26 27 28 for (int i = 0; i < n; ++i) {29 while (!stack.empty() && primeScores[stack.top()] < primeScores[i])30 right[stack.top()] = i, stack.pop();31 stack.push(i);32 }33 34 vector<pair<int, int>> numAndIndexes;35 36 for (int i = 0; i < n; ++i)37 numAndIndexes.emplace_back(nums[i], i);38 39 ranges::sort(numAndIndexes,40 [&](const pair<int, int>& a, const pair<int, int>& b) {41 return a.first == b.first ? a.second < b.second : a.first > b.first;42 });43 44 for (const auto& [num, i] : numAndIndexes) {45 46 47 48 const long rangeCount = static_cast<long>(i - left[i]) * (right[i] - i);49 const long actualCount = min(rangeCount, static_cast<long>(k));50 k -= actualCount;51 ans = static_cast<long>(ans) * modPow(num, actualCount) % kMod;52 }53 54 return ans;55 }56 57 private:58 static constexpr int kMod = 1'000'000'007;59 60 long modPow(long x, long n) {61 if (n == 0)62 return 1;63 if (n % 2 == 1)64 return x * modPow(x % kMod, (n - 1)) % kMod;65 return modPow(x * x % kMod, (n / 2)) % kMod;66 }67 68 69 vector<int> sieveEratosthenes(int n) {70 vector<int> minPrimeFactors(n + 1);71 iota(minPrimeFactors.begin() + 2, minPrimeFactors.end(), 2);72 for (int i = 2; i * i < n; ++i)73 if (minPrimeFactors[i] == i) 74 for (int j = i * i; j < n; j += i)75 minPrimeFactors[j] = min(minPrimeFactors[j], i);76 return minPrimeFactors;77 }78 79 vector<int> getPrimeScores(const vector<int>& nums,80 const vector<int>& minPrimeFactors) {81 vector<int> primeScores;82 for (const int num : nums)83 primeScores.push_back(getPrimeScore(num, minPrimeFactors));84 return primeScores;85 }86 87 int getPrimeScore(int num, const vector<int>& minPrimeFactors) {88 unordered_set<int> primeFactors;89 while (num > 1) {90 const int divisor = minPrimeFactors[num];91 primeFactors.insert(divisor);92 while (num % divisor == 0)93 num /= divisor;94 }95 return primeFactors.size();96 }97};98