- 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
- 116 lines of C++ from the credited upstream file 3501.cpp.
- The implementation visibly relies on sequence storage, ordered lookup.
- 5 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.
1#include <ranges>2 3struct Group {4 int start;5 int length;6};7 8class SparseTable {9 public:10 SparseTable(const vector<int>& nums)11 : n(nums.size()), st(std::bit_width(n) + 1, vector<int>(n + 1)) {12 copy(nums.begin(), nums.end(), st[0].begin());13 for (int i = 1; i <= bit_width(n); ++i)14 for (int j = 0; j + (1 << i) <= n; ++j)15 st[i][j] = max(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);16 }17 18 19 int query(unsigned l, unsigned r) const {20 const int i = bit_width(r - l + 1) - 1;21 return max(st[i][l], st[i][r - (1 << i) + 1]);22 }23 24 private:25 const unsigned n;26 vector<vector<int>> st; 27};28 29class Solution {30 public:31 vector<int> maxActiveSectionsAfterTrade(string s,32 vector<vector<int>>& queries) {33 const int n = s.length();34 const int ones = ranges::count(s, '1');35 const auto [zeroGroups, zeroGroupIndex] = getZeroGroups(s);36 if (zeroGroups.empty())37 return vector<int>(queries.size(), ones);38 39 const SparseTable st(getZeroMergeLengths(zeroGroups));40 vector<int> ans;41 42 for (const vector<int>& query : queries) {43 const int l = query[0];44 const int r = query[1];45 const int left = zeroGroupIndex[l] == -146 ? -147 : (zeroGroups[zeroGroupIndex[l]].length -48 (l - zeroGroups[zeroGroupIndex[l]].start));49 const int right = zeroGroupIndex[r] == -150 ? -151 : (r - zeroGroups[zeroGroupIndex[r]].start + 1);52 const auto [startAdjacentGroupIndex, endAdjacentGroupIndex] =53 mapToAdjacentGroupIndices(54 zeroGroupIndex[l] + 1,55 s[r] == '1' ? zeroGroupIndex[r] : zeroGroupIndex[r] - 1);56 int activeSections = ones;57 if (s[l] == '0' && s[r] == '0' &&58 zeroGroupIndex[l] + 1 == zeroGroupIndex[r])59 activeSections = max(activeSections, ones + left + right);60 else if (startAdjacentGroupIndex <= endAdjacentGroupIndex)61 activeSections = max(62 activeSections,63 ones + st.query(startAdjacentGroupIndex, endAdjacentGroupIndex));64 if (s[l] == '0' &&65 zeroGroupIndex[l] + 1 <=66 (s[r] == '1' ? zeroGroupIndex[r] : zeroGroupIndex[r] - 1))67 activeSections =68 max(activeSections,69 ones + left + zeroGroups[zeroGroupIndex[l] + 1].length);70 if (s[r] == '0' && zeroGroupIndex[l] < zeroGroupIndex[r] - 1)71 activeSections =72 max(activeSections,73 ones + right + zeroGroups[zeroGroupIndex[r] - 1].length);74 ans.push_back(activeSections);75 }76 77 return ans;78 }79 80 private:81 82 83 pair<vector<Group>, vector<int>> getZeroGroups(const string& s) {84 vector<Group> zeroGroups;85 vector<int> zeroGroupIndex;86 for (int i = 0; i < s.length(); i++) {87 if (s[i] == '0') {88 if (i > 0 && s[i - 1] == '0')89 ++zeroGroups.back().length;90 else91 zeroGroups.push_back({i, 1});92 }93 zeroGroupIndex.push_back(zeroGroups.size() - 1);94 }95 return {zeroGroups, zeroGroupIndex};96 }97 98 99 vector<int> getZeroMergeLengths(const vector<Group>& zeroGroups) {100 vector<int> zeroMergeLengths;101 for (const auto& [a, b] : zeroGroups | views::pairwise)102 zeroMergeLengths.push_back(a.length + b.length);103 return zeroMergeLengths;104 }105 106 107 108 109 110 111 pair<int, int> mapToAdjacentGroupIndices(int startGroupIndex,112 int endGroupIndex) {113 return {startGroupIndex, endGroupIndex - 1};114 }115};116