- 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
- 63 lines of C++ from the credited upstream file 3261.cpp.
- The implementation visibly relies on sequence storage.
- 6 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 vector<long long> countKConstraintSubstrings(string s, int k,4 vector<vector<int>>& queries) {5 const int n = s.size();6 vector<long long> ans;7 vector<int> count(2);8 9 vector<int> leftToRight(n);10 11 vector<int> rightToLeft(n);12 13 vector<long> prefix{0};14 15 for (int l = 0, r = 0; r < n; ++r) {16 ++count[s[r] - '0'];17 while (count[0] > k && count[1] > k)18 --count[s[l++] - '0'];19 rightToLeft[r] = l;20 }21 22 count = vector<int>(2);23 24 for (int l = n - 1, r = n - 1; l >= 0; --l) {25 ++count[s[l] - '0'];26 while (count[0] > k && count[1] > k)27 --count[s[r--] - '0'];28 leftToRight[l] = r;29 }30 31 for (int r = 0; r < n; ++r)32 prefix.push_back(prefix.back() + r - rightToLeft[r] + 1);33 34 for (const vector<int>& query : queries) {35 const int l = query[0];36 const int r = query[1];37 long numValidSubstrings = 0;38 if (r > leftToRight[l]) {39 40 41 42 43 44 45 46 47 48 const int sz = leftToRight[l] - l + 1;49 numValidSubstrings =50 (sz * (sz + 1)) / 2 + (prefix[r + 1] - prefix[leftToRight[l] + 1]);51 } else {52 53 54 const int sz = r - l + 1;55 numValidSubstrings = (sz * static_cast<long>(sz + 1)) / 2;56 }57 ans.push_back(numValidSubstrings);58 }59 60 return ans;61 }62};63