# Count of substrings in a Binary String that contains more 1s than 0s

Given a binary string s, the task is to calculate the number of such substrings where the count of 1‘s is strictly greater than the count of 0‘s.

Examples

Input: S = “110011”
Output: 11
Explanation:
Substrings in which the count of 1’s is strictly greater than the count of 0’s are { S[0]}, {S[0], S[1]}, {S[0], S[2]}, {S[0], S[4]}, {S[0], S[5]}, {S[1], S[1]}, {S[1], S[5]}, {S[3], S[5]}, {S[4], S[4]}, {S[4], S[5]}, {S[5], S[5]}.

Input: S = “101”
Output: 3

Naive Approach: The simplest approach to solve the problem is to generate all substrings and count the number of 1s and 0s in each substring. Increase the count of those substrings that contain the count of 1s greater than the count of 0s. Finally, print the count obtained.
Time Complexity: O(N3)
Auxiliary Space: O(1)

Efficient Approach: The above approach can be optimized using Merge Sort Algorithm. Follow the steps below:

• Initialize an array, say nums[] of size n, where n is the length of the string.
• Traverse the string. If s[i]  == ‘1’, then store 1 in nums[i]. Otherwise, set nums[i] = -1.
• Update pref[] to store the prefix sum of the array nums[].
• Now, the problem reduces to counting the number of pairs(i, j) in the array pref[], where pref[i] < pref[j] and i < j, which is similar to counting inversions in an array from the rear side.
• Return the number of inversions of the prefix sum array as the final answer.

Below is the implementation of the above approach.

## C++14

 `// C++ program for the above approach` `#include ` `using` `namespace` `std;`   `// Function to merge two partitions` `// such that the merged array is sorted` `void` `merge(vector<``int``>& v, ``int` `left,` `           ``int` `mid, ``int` `right, ``int``& inversions)` `{` `    ``vector<``int``> temp(right - left + 1);`   `    ``int` `i = left;` `    ``int` `j = mid + 1;` `    ``int` `k = 0;` `    ``int` `cnt = 0;`   `    ``while` `(i <= mid && j <= right) {` `        ``if` `(v[i] <= v[j]) {` `            ``temp[k++] = v[i++];` `        ``}` `        ``else` `{` `            ``// Counting inversions` `            ``inversions += (mid - i + 1);`   `            ``temp[k++] = v[j++];` `        ``}` `    ``}`   `    ``while` `(i <= mid)` `        ``temp[k++] = v[i++];`   `    ``while` `(j <= right)` `        ``temp[k++] = v[j++];`   `    ``k = 0;` `    ``for` `(``int` `a = left; a <= right; a++) {` `        ``v[a] = temp[k++];` `    ``}` `}`   `// Function to implement merge sort` `void` `mergeSort(vector<``int``>& v, ``int` `left,` `               ``int` `right, ``int``& inversions)` `{` `    ``if` `(left < right) {` `        ``int` `mid = (left + right) / 2;`   `        ``mergeSort(v, left, mid, inversions);` `        ``mergeSort(v, mid + 1, right, inversions);` `        ``merge(v, left, mid, right, inversions);` `    ``}` `}`   `// Function to calculate number of` `// inversions in a given array` `int` `CountInversions(vector<``int``>& v)` `{` `    ``int` `n = v.size();` `    ``int` `inversions = 0;`   `    ``// Calculate the number of inversions` `    ``mergeSort(v, 0, n - 1, inversions);`   `    ``// Return the number of inversions` `    ``return` `inversions;` `}`   `// Function to count the number of` `// substrings that contains more 1s than 0s` `int` `getSubsCount(string& input)` `{` `    ``int` `n = input.length();`   `    ``vector<``int``> nums(n);`   `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``nums[i] = input[i] - ``'0'``;`   `        ``if` `(nums[i] == 0)` `            ``nums[i] = -1;` `    ``}`   `    ``// Stores the prefix sum array` `    ``vector<``int``> pref(n);`   `    ``int` `sum = 0;`   `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``sum += nums[i];` `        ``pref[i] = sum;` `    ``}`   `    ``int` `cnt = 0;`   `    ``// Stores the count of valid substrings` `    ``for` `(``int` `i = 0; i < n; i++) {` `        ``if` `(pref[i] > 0)` `            ``cnt++;` `    ``}`   `    ``reverse(pref.begin(), pref.end());`   `    ``int` `inversions = CountInversions(pref);`   `    ``int` `ans = cnt + inversions;`   `    ``return` `ans;` `}`   `// Driver Code` `int` `main()` `{`   `    ``// Given Input` `    ``string input = ``"10011101"``;`   `    ``// Function Call` `    ``int` `ans = getSubsCount(input);`   `    ``cout << ans << endl;`   `    ``return` `0;` `}`

## Java

 `import` `java.util.Arrays;`   `public` `class` `SubstringsCount {`   `    ``public` `static` `void` `merge(``int``[] arr, ``int` `left, ``int` `mid, ``int` `right, ``int``[] inversions) {` `        ``// Merge two sorted partitions and count inversions` `        ``int``[] temp = ``new` `int``[right - left + ``1``];` `        ``int` `i = left;` `        ``int` `j = mid + ``1``;` `        ``int` `k = ``0``;`   `        ``while` `(i <= mid && j <= right) {` `            ``if` `(arr[i] <= arr[j]) {` `                ``temp[k] = arr[i];` `                ``k++;` `                ``i++;` `            ``} ``else` `{` `                ``// Counting inversions when an element from the right partition is chosen` `                ``inversions[``0``] += (mid - i + ``1``);` `                ``temp[k] = arr[j];` `                ``k++;` `                ``j++;` `            ``}` `        ``}`   `        ``while` `(i <= mid) {` `            ``temp[k] = arr[i];` `            ``k++;` `            ``i++;` `        ``}`   `        ``while` `(j <= right) {` `            ``temp[k] = arr[j];` `            ``k++;` `            ``j++;` `        ``}`   `        ``k = ``0``;` `        ``for` `(``int` `a = left; a <= right; a++) {` `            ``arr[a] = temp[k];` `            ``k++;` `        ``}` `    ``}`   `    ``public` `static` `void` `mergeSort(``int``[] arr, ``int` `left, ``int` `right, ``int``[] inversions) {` `        ``// Recursive merge sort algorithm` `        ``if` `(left < right) {` `            ``int` `mid = (left + right) / ``2``;` `            ``mergeSort(arr, left, mid, inversions);` `            ``mergeSort(arr, mid + ``1``, right, inversions);` `            ``merge(arr, left, mid, right, inversions);` `        ``}` `    ``}`   `    ``public` `static` `int` `countInversions(``int``[] arr) {` `        ``// Calculate the number of inversions using the modified merge sort` `        ``int``[] inversions = {``0``};` `        ``mergeSort(arr, ``0``, arr.length - ``1``, inversions);` `        ``return` `inversions[``0``];` `    ``}`   `    ``public` `static` `int` `getSubsCount(String inputStr) {` `        ``int` `n = inputStr.length();` `        ``int``[] nums = ``new` `int``[n];`   `        ``// Convert binary string to an array of 1s and -1s` `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``nums[i] = Character.getNumericValue(inputStr.charAt(i));` `            ``if` `(nums[i] == ``0``) {` `                ``nums[i] = -``1``;` `            ``}` `        ``}`   `        ``int``[] pref = ``new` `int``[n];` `        ``int` `s = ``0``;`   `        ``// Calculate the prefix sum array` `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``s += nums[i];` `            ``pref[i] = s;` `        ``}`   `        ``// Count the number of valid substrings` `        ``int` `cnt = (``int``) Arrays.stream(pref).filter(x -> x > ``0``).count();`   `        ``// Reverse the prefix sum array` `        ``for` `(``int` `i = ``0``; i < n / ``2``; i++) {` `            ``int` `temp = pref[i];` `            ``pref[i] = pref[n - ``1` `- i];` `            ``pref[n - ``1` `- i] = temp;` `        ``}`   `        ``// Calculate the number of inversions in the reversed prefix sum array` `        ``int` `inversions = countInversions(pref);`   `        ``// Calculate the final result by adding counts of valid substrings and inversions` `        ``return` `cnt + inversions;` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `main(String[] args) {` `        ``// Given Input` `        ``String inputStr = ``"10011101"``;`   `        ``// Function Call` `        ``int` `ans = getSubsCount(inputStr);`   `        ``// Print the result` `        ``System.out.println(ans);` `    ``}` `}`

## Python3

 `def` `merge(arr, left, mid, right, inversions):` `    ``# Merge two sorted partitions and count inversions` `    ``temp ``=` `[``0``] ``*` `(right ``-` `left ``+` `1``)` `    ``i ``=` `left` `    ``j ``=` `mid ``+` `1` `    ``k ``=` `0`   `    ``while` `i <``=` `mid ``and` `j <``=` `right:` `        ``if` `arr[i] <``=` `arr[j]:` `            ``temp[k] ``=` `arr[i]` `            ``k ``+``=` `1` `            ``i ``+``=` `1` `        ``else``:` `            ``# Counting inversions when an element from the right partition is chosen` `            ``inversions[``0``] ``+``=` `(mid ``-` `i ``+` `1``)` `            ``temp[k] ``=` `arr[j]` `            ``k ``+``=` `1` `            ``j ``+``=` `1`   `    ``while` `i <``=` `mid:` `        ``temp[k] ``=` `arr[i]` `        ``k ``+``=` `1` `        ``i ``+``=` `1`   `    ``while` `j <``=` `right:` `        ``temp[k] ``=` `arr[j]` `        ``k ``+``=` `1` `        ``j ``+``=` `1`   `    ``k ``=` `0` `    ``for` `a ``in` `range``(left, right ``+` `1``):` `        ``arr[a] ``=` `temp[k]` `        ``k ``+``=` `1`     `def` `merge_sort(arr, left, right, inversions):` `    ``# Recursive merge sort algorithm` `    ``if` `left < right:` `        ``mid ``=` `(left ``+` `right) ``/``/` `2` `        ``merge_sort(arr, left, mid, inversions)` `        ``merge_sort(arr, mid ``+` `1``, right, inversions)` `        ``merge(arr, left, mid, right, inversions)`     `def` `count_inversions(arr):` `    ``# Calculate the number of inversions using the modified merge sort` `    ``n ``=` `len``(arr)` `    ``inversions ``=` `[``0``]` `    ``merge_sort(arr, ``0``, n ``-` `1``, inversions)` `    ``return` `inversions[``0``]`     `def` `get_subs_count(input_str):` `    ``n ``=` `len``(input_str)` `    ``nums ``=` `[``0``] ``*` `n`   `    ``# Convert binary string to an array of 1s and -1s` `    ``for` `i ``in` `range``(n):` `        ``nums[i] ``=` `int``(input_str[i])` `        ``if` `nums[i] ``=``=` `0``:` `            ``nums[i] ``=` `-``1`   `    ``pref ``=` `[``0``] ``*` `n` `    ``s ``=` `0`   `    ``# Calculate the prefix sum array` `    ``for` `i ``in` `range``(n):` `        ``s ``+``=` `nums[i]` `        ``pref[i] ``=` `s`   `    ``# Count the number of valid substrings` `    ``cnt ``=` `sum``(``1` `for` `x ``in` `pref ``if` `x > ``0``)`   `    ``# Reverse the prefix sum array` `    ``pref.reverse()`   `    ``# Calculate the number of inversions in the reversed prefix sum array` `    ``inversions ``=` `count_inversions(pref)`   `    ``# Calculate the final result by adding counts of valid substrings and inversions` `    ``ans ``=` `cnt ``+` `inversions`   `    ``return` `ans`     `# Driver Code` `if` `__name__ ``=``=` `"__main__"``:` `    ``# Given Input` `    ``input_str ``=` `"10011101"`   `    ``# Function Call` `    ``ans ``=` `get_subs_count(input_str)`   `    ``# Print the result` `    ``print``(ans)`

## C#

 `using` `System;` `using` `System.Linq;`   `public` `class` `SubstringsCount` `{` `    ``public` `static` `void` `Merge(``int``[] arr, ``int` `left, ``int` `mid, ``int` `right, ``int``[] inversions)` `    ``{` `        ``// Merge two sorted partitions and count inversions` `        ``int``[] temp = ``new` `int``[right - left + 1];` `        ``int` `i = left;` `        ``int` `j = mid + 1;` `        ``int` `k = 0;`   `        ``while` `(i <= mid && j <= right)` `        ``{` `            ``if` `(arr[i] <= arr[j])` `            ``{` `                ``temp[k] = arr[i];` `                ``k++;` `                ``i++;` `            ``}` `            ``else` `            ``{` `                ``// Counting inversions when an element from the right partition is chosen` `                ``inversions[0] += (mid - i + 1);` `                ``temp[k] = arr[j];` `                ``k++;` `                ``j++;` `            ``}` `        ``}`   `        ``while` `(i <= mid)` `        ``{` `            ``temp[k] = arr[i];` `            ``k++;` `            ``i++;` `        ``}`   `        ``while` `(j <= right)` `        ``{` `            ``temp[k] = arr[j];` `            ``k++;` `            ``j++;` `        ``}`   `        ``k = 0;` `        ``for` `(``int` `a = left; a <= right; a++)` `        ``{` `            ``arr[a] = temp[k];` `            ``k++;` `        ``}` `    ``}`   `    ``public` `static` `void` `MergeSort(``int``[] arr, ``int` `left, ``int` `right, ``int``[] inversions)` `    ``{` `        ``// Recursive merge sort algorithm` `        ``if` `(left < right)` `        ``{` `            ``int` `mid = (left + right) / 2;` `            ``MergeSort(arr, left, mid, inversions);` `            ``MergeSort(arr, mid + 1, right, inversions);` `            ``Merge(arr, left, mid, right, inversions);` `        ``}` `    ``}`   `    ``public` `static` `int` `CountInversions(``int``[] arr)` `    ``{` `        ``// Calculate the number of inversions using the modified merge sort` `        ``int``[] inversions = { 0 };` `        ``MergeSort(arr, 0, arr.Length - 1, inversions);` `        ``return` `inversions[0];` `    ``}`   `    ``public` `static` `int` `GetSubsCount(``string` `inputStr)` `    ``{` `        ``int` `n = inputStr.Length;` `        ``int``[] nums = ``new` `int``[n];`   `        ``// Convert binary string to an array of 1s and -1s` `        ``for` `(``int` `i = 0; i < n; i++)` `        ``{` `            ``nums[i] = ``int``.Parse(inputStr[i].ToString());` `            ``if` `(nums[i] == 0)` `            ``{` `                ``nums[i] = -1;` `            ``}` `        ``}`   `        ``int``[] pref = ``new` `int``[n];` `        ``int` `s = 0;`   `        ``// Calculate the prefix sum array` `        ``for` `(``int` `i = 0; i < n; i++)` `        ``{` `            ``s += nums[i];` `            ``pref[i] = s;` `        ``}`   `        ``// Count the number of valid substrings` `        ``int` `cnt = pref.Count(x => x > 0);`   `        ``// Reverse the prefix sum array` `        ``Array.Reverse(pref);`   `        ``// Calculate the number of inversions in the reversed prefix sum array` `        ``int` `inversions = CountInversions(pref);`   `        ``// Calculate the final result by adding counts of valid substrings and inversions` `        ``return` `cnt + inversions;` `    ``}`   `    ``// Driver Code` `    ``public` `static` `void` `Main(``string``[] args)` `    ``{` `        ``// Given Input` `        ``string` `inputStr = ``"10011101"``;`   `        ``// Function Call` `        ``int` `ans = GetSubsCount(inputStr);`   `        ``// Print the result` `        ``Console.WriteLine(ans);` `    ``}` `}`

## Javascript

 `class SubstringsCount {` `    ``static merge(arr, left, mid, right, inversions) {` `        ``// Merge two sorted partitions and count inversions` `        ``let temp = ``new` `Array(right - left + 1);` `        ``let i = left;` `        ``let j = mid + 1;` `        ``let k = 0;`   `        ``while` `(i <= mid && j <= right) {` `            ``if` `(arr[i] <= arr[j]) {` `                ``temp[k] = arr[i];` `                ``k++;` `                ``i++;` `            ``} ``else` `{` `                ``// Counting inversions when an element from the right partition is chosen` `                ``inversions[0] += (mid - i + 1);` `                ``temp[k] = arr[j];` `                ``k++;` `                ``j++;` `            ``}` `        ``}`   `        ``while` `(i <= mid) {` `            ``temp[k] = arr[i];` `            ``k++;` `            ``i++;` `        ``}`   `        ``while` `(j <= right) {` `            ``temp[k] = arr[j];` `            ``k++;` `            ``j++;` `        ``}`   `        ``k = 0;` `        ``for` `(let a = left; a <= right; a++) {` `            ``arr[a] = temp[k];` `            ``k++;` `        ``}` `    ``}`   `    ``static mergeSort(arr, left, right, inversions) {` `        ``// Recursive merge sort algorithm` `        ``if` `(left < right) {` `            ``let mid = Math.floor((left + right) / 2);` `            ``this``.mergeSort(arr, left, mid, inversions);` `            ``this``.mergeSort(arr, mid + 1, right, inversions);` `            ``this``.merge(arr, left, mid, right, inversions);` `        ``}` `    ``}`   `    ``static countInversions(arr) {` `        ``// Calculate the number of inversions using the modified merge sort` `        ``let inversions = [0];` `        ``this``.mergeSort(arr, 0, arr.length - 1, inversions);` `        ``return` `inversions[0];` `    ``}`   `    ``static getSubsCount(inputStr) {` `        ``let n = inputStr.length;` `        ``let nums = ``new` `Array(n);`   `        ``// Convert binary string to an array of 1s and -1s` `        ``for` `(let i = 0; i < n; i++) {` `            ``nums[i] = parseInt(inputStr[i]);` `            ``if` `(nums[i] === 0) {` `                ``nums[i] = -1;` `            ``}` `        ``}`   `        ``let pref = ``new` `Array(n);` `        ``let s = 0;`   `        ``// Calculate the prefix sum array` `        ``for` `(let i = 0; i < n; i++) {` `            ``s += nums[i];` `            ``pref[i] = s;` `        ``}`   `        ``// Count the number of valid substrings` `        ``let cnt = pref.filter(x => x > 0).length;`   `        ``// Reverse the prefix sum array` `        ``pref.reverse();`   `        ``// Calculate the number of inversions in the reversed prefix sum array` `        ``let inversions = ``this``.countInversions(pref);`   `        ``// Calculate the final result by adding counts of valid substrings and inversions` `        ``return` `cnt + inversions;` `    ``}` `}`   `// Driver Code` `let inputStr = ``"10011101"``;` `let ans = SubstringsCount.getSubsCount(inputStr);` `console.log(ans);`

Output

```23

```

Time Complexity: O(NlogN)
Auxiliary Space: O(N)

## Segment Tree Approach

The below code uses segment tree. This approach is also O(NlogN) and can be seen yet as another approach.

The subarray [i,j] should have atleast sum 1, if we consider -1 for ‘0’ and 1 for ‘1’.

### Using segment tree, count all prefix[i] which are less than or equal to for 1 – prefix[j].

Now, here is one more thing. What if the string has a negative prefix sum, i.e S=”001″. The prefix sum at index 1 is -2. You cannot have negative indices / ranges in segment tree.

For that we do index shifting. Simply saying, its like shifting the origin by some value.

This helps us in overcoming negative ranges in segment tree. If N<=100000, So the highest prefix sum can be 100000 and the lowest prefix sum can be -100000. You cannot have negative range/index for segment tree. So -100000 won’t be possible.

If we add 100000 from our side manually. The new highest and lowest becomes 200000 and 0 respectively. As you can see, the relative distance still is the same, but there is no negative and hence can be used in segment tree.

For any string S, the shift value will be the size of the string.

Follow the steps below to implement the above idea:

1) Make a vector “tree”, and resize it according to the size of the input. Hereby, 4*(2*n)+1. 2*n because of the shift phenomenon as explained before. For any string S, the shift value will be the size of the string.2) Use the generic code for update and query function in segment tree.

3) Update the current running sum i.e. 0+shiftValue in the segment tree. Zero sum because there is no prefix sum as of now.

4) Iterate from i=0 to n. For S[i]=’1′ ,add 1 and for S[i]=’0′ , add -1. As discussed earlier, we will add shift value to this sum and search for the number of indices where prefix sum was less than or equal to (currSum + shift) – 1. For this, we search in the range 0 to (currSum + shift) – 1, as the lowest possible value can be 0, because of shifting and the highest value we can have is (currSum + shift) – 1. Add the number of indices to the answer.

5) Update the current running prefix sum with its shift value added to it, i.e. update currSum+shift in the segment tree.

6) Return the answer after the loop is terminated.

## C++

 `// Author - RainX (Abhijit Roy, NIT AGARTALA) `   `#include ` `using` `namespace` `std;`   `vector<``int``> tree;`   `void` `update(``int` `start, ``int` `end, ``int` `parent, ``long` `long` `index){` `   ``if` `(start > end) {` `       ``return``;` `   ``}` `   ``if` `(start == end) {` `       ``tree[parent]++;` `       ``return``;` `   ``}` `   ``int` `mid = (start + end) / 2;` `   ``if` `(index > mid) {` `       ``update(mid + 1, end, 2 * parent + 2, index);` `   ``}` `   ``else` `{` `       ``update(start, mid, 2 * parent + 1, index);` `   ``}` `   ``tree[parent] = tree[2 * parent + 1] + tree[2 * parent + 2];` `}`   `int` `query(``int` `start, ``int` `end, ``int` `parent, ``int` `qstart, ``int` `qend){` `   ``if` `(qstart > end || qend < start) {` `       ``return` `0;` `   ``}` `   ``if` `(qstart <= start && qend >= end) {` `       ``return` `tree[parent];` `   ``}` `   ``int` `mid = (start + end) / 2;` `   ``int` `L = query(start, mid, 2 * parent + 1, qstart, qend);` `   ``int` `R = query(mid + 1, end, 2 * parent + 2, qstart, qend);` `   ``return` `L + R;` `}`   `int` `getSubsCount(string &S){` `   ``int` `n = S.size();` `   ``tree.resize(4 * 2 * n + 1, 0);`   `   ``int` `shift = n;` `   ``long` `long` `currSum = 0;` `   ``long` `long` `cnt = 0;`   `   ``update(0, 2 * n, 0, 0 + shift);` `  `  `   ``for` `(``int` `i = 0; i < n; i++) {` `       ``currSum += (S[i] == ``'1'` `? 1 : -1);`   `       ``/*    prefix[j]-prefix[i]>=1` `          ``=> prefix[i]<=prefix[j]-1` `       ``*/` `     `  `       ``int` `lessThan = (currSum + shift) - 1;` `       ``cnt += query(0, 2 * n, 0, 0, lessThan);`   `       ``update(0, 2 * n, 0, currSum + shift);` `   ``}` `   ``return` `cnt;` `}`   `int` `main(){` `   ``string input = ``"10011101"``;`   `   ``int` `ans = getSubsCount(input);`   `   ``cout << ans << endl;`   `   ``return` `0;` `}`   `// Author - RainX (Abhijit Roy, NIT AGARTALA,2023)`

## Java

 `import` `java.util.*;`   `class` `Main {` `    ``static` `List tree;`   `    ``static` `void` `update(``int` `start, ``int` `end, ``int` `parent, ``long` `index) {` `        ``if` `(start > end) {` `            ``return``;` `        ``}` `        ``if` `(start == end) {` `            ``tree.set(parent, tree.get(parent) + ``1``);` `            ``return``;` `        ``}` `        ``int` `mid = (start + end) / ``2``;` `        ``if` `(index > mid) {` `            ``update(mid + ``1``, end, ``2` `* parent + ``2``, index);` `        ``}` `        ``else` `{` `            ``update(start, mid, ``2` `* parent + ``1``, index);` `        ``}` `        ``tree.set(parent, tree.get(``2` `* parent + ``1``) + tree.get(``2` `* parent + ``2``));` `    ``}`   `    ``static` `int` `query(``int` `start, ``int` `end, ``int` `parent, ``int` `qstart, ``int` `qend) {` `        ``if` `(qstart > end || qend < start) {` `            ``return` `0``;` `        ``}` `        ``if` `(qstart <= start && qend >= end) {` `            ``return` `tree.get(parent);` `        ``}` `        ``int` `mid = (start + end) / ``2``;` `        ``int` `L = query(start, mid, ``2` `* parent + ``1``, qstart, qend);` `        ``int` `R = query(mid + ``1``, end, ``2` `* parent + ``2``, qstart, qend);` `        ``return` `L + R;` `    ``}`   `    ``static` `int` `getSubsCount(String S) {` `        ``int` `n = S.length();` `        ``tree = ``new` `ArrayList(Collections.nCopies(``4` `* ``2` `* n + ``1``, ``0``));`   `        ``int` `shift = n;` `        ``long` `currSum = ``0``;` `        ``long` `cnt = ``0``;`   `        ``update(``0``, ``2` `* n, ``0``, ``0` `+ shift);`   `        ``for` `(``int` `i = ``0``; i < n; i++) {` `            ``currSum += (S.charAt(i) == ``'1'` `? ``1` `: -``1``);`   `            ``/*    prefix[j]-prefix[i]>=1` `                ``=> prefix[i]<=1-prefix[j]` `            ``*/`   `            ``int` `lessThan = (``int``) (currSum + shift) - ``1``;` `            ``cnt += query(``0``, ``2` `* n, ``0``, ``0``, lessThan);`   `            ``update(``0``, ``2` `* n, ``0``, currSum + shift);` `        ``}` `        ``return` `(``int``) cnt;` `    ``}`   `    ``public` `static` `void` `main(String[] args) {` `        ``String input = ``"10011101"``;` `        ``int` `ans = getSubsCount(input);` `        ``System.out.println(ans);` `    ``}` `}`

## Python3

 `from` `typing ``import` `List`     `def` `update(start: ``int``, end: ``int``, parent: ``int``, index: ``int``) ``-``> ``None``:` `    ``if` `start > end:` `        ``return` `    ``if` `start ``=``=` `end:` `        ``tree[parent] ``+``=` `1` `        ``return` `    ``mid ``=` `(start ``+` `end) ``/``/` `2` `    ``if` `index > mid:` `        ``update(mid ``+` `1``, end, ``2` `*` `parent ``+` `2``, index)` `    ``else``:` `        ``update(start, mid, ``2` `*` `parent ``+` `1``, index)` `    ``tree[parent] ``=` `tree[``2` `*` `parent ``+` `1``] ``+` `tree[``2` `*` `parent ``+` `2``]`     `def` `query(start: ``int``, end: ``int``, parent: ``int``, qstart: ``int``, qend: ``int``) ``-``> ``int``:` `    ``if` `qstart > end ``or` `qend < start:` `        ``return` `0` `    ``if` `qstart <``=` `start ``and` `qend >``=` `end:` `        ``return` `tree[parent]` `    ``mid ``=` `(start ``+` `end) ``/``/` `2` `    ``L ``=` `query(start, mid, ``2` `*` `parent ``+` `1``, qstart, qend)` `    ``R ``=` `query(mid ``+` `1``, end, ``2` `*` `parent ``+` `2``, qstart, qend)` `    ``return` `L ``+` `R`     `def` `getSubsCount(S: ``str``) ``-``> ``int``:` `    ``n ``=` `len``(S)` `    ``global` `tree` `    ``tree ``=` `[``0``] ``*` `(``4` `*` `2` `*` `n ``+` `1``)`   `    ``shift ``=` `n` `    ``currSum ``=` `0` `    ``cnt ``=` `0`   `    ``update(``0``, ``2` `*` `n, ``0``, ``0` `+` `shift)`   `    ``for` `i ``in` `range``(n):` `        ``currSum ``+``=` `1` `if` `S[i] ``=``=` `'1'` `else` `-``1`   `        ``"""` `        ``prefix[j] - prefix[i] >= 1` `        ``=> prefix[i] <= 1 - prefix[j]` `        ``"""`   `        ``lessThan ``=` `int``(currSum ``+` `shift) ``-` `1` `        ``cnt ``+``=` `query(``0``, ``2` `*` `n, ``0``, ``0``, lessThan)`   `        ``update(``0``, ``2` `*` `n, ``0``, ``int``(currSum ``+` `shift))`   `    ``return` `cnt`     `if` `__name__ ``=``=` `'__main__'``:` `    ``input_str ``=` `"10011101"` `    ``ans ``=` `getSubsCount(input_str)` `    ``print``(ans)`

## C#

 `using` `System;` `using` `System.Collections.Generic;`   `public` `class` `MainClass {` `    ``static` `List<``int``> tree;`   `    ``static` `void` `update(``int` `start, ``int` `end, ``int` `parent, ``long` `index) {` `        ``if` `(start > end) {` `            ``return``;` `        ``}` `        ``if` `(start == end) {` `            ``tree[parent] += 1;` `            ``return``;` `        ``}` `        ``int` `mid = (start + end) / 2;` `        ``if` `(index > mid) {` `            ``update(mid + 1, end, 2 * parent + 2, index);` `        ``}` `        ``else` `{` `            ``update(start, mid, 2 * parent + 1, index);` `        ``}` `        ``tree[parent] = tree[2 * parent + 1] + tree[2 * parent + 2];` `    ``}`   `    ``static` `int` `query(``int` `start, ``int` `end, ``int` `parent, ``int` `qstart, ``int` `qend) {` `        ``if` `(qstart > end || qend < start) {` `            ``return` `0;` `        ``}` `        ``if` `(qstart <= start && qend >= end) {` `            ``return` `tree[parent];` `        ``}` `        ``int` `mid = (start + end) / 2;` `        ``int` `L = query(start, mid, 2 * parent + 1, qstart, qend);` `        ``int` `R = query(mid + 1, end, 2 * parent + 2, qstart, qend);` `        ``return` `L + R;` `    ``}`   `    ``static` `int` `getSubsCount(``string` `S) {` `        ``int` `n = S.Length;` `        ``tree = ``new` `List<``int``>(``new` `int``[4 * 2 * n + 1]);`   `        ``int` `shift = n;` `        ``long` `currSum = 0;` `        ``long` `cnt = 0;`   `        ``update(0, 2 * n, 0, 0 + shift);`   `        ``for` `(``int` `i = 0; i < n; i++) {` `            ``currSum += (S[i] == ``'1'` `? 1 : -1);`   `            ``/*    prefix[j]-prefix[i]>=1` `                ``=> prefix[i]<=1-prefix[j]` `            ``*/`   `            ``int` `lessThan = (``int``) (currSum + shift) - 1;` `            ``cnt += query(0, 2 * n, 0, 0, lessThan);`   `            ``update(0, 2 * n, 0, currSum + shift);` `        ``}` `        ``return` `(``int``) cnt;` `    ``}`   `    ``public` `static` `void` `Main() {` `        ``string` `input = ``"10011101"``;` `         ``int` `ans = getSubsCount(input);` `       ``Console.WriteLine(ans);` `    ``}` `}`

## Javascript

 `function` `update(start, end, parent, index, tree) {` `    ``if` `(start > end) {` `        ``return``;` `    ``}` `    ``if` `(start == end) {` `        ``tree[parent] += 1;` `        ``return``;` `    ``}` `    ``const mid = Math.floor((start + end) / 2);` `    ``if` `(index > mid) {` `        ``update(mid + 1, end, 2 * parent + 2, index, tree);` `    ``}` `    ``else` `{` `        ``update(start, mid, 2 * parent + 1, index, tree);` `    ``}` `    ``tree[parent] = tree[2 * parent + 1] + tree[2 * parent + 2];` `}`   `function` `query(start, end, parent, qstart, qend, tree) {` `    ``if` `(qstart > end || qend < start) {` `        ``return` `0;` `    ``}` `    ``if` `(qstart <= start && qend >= end) {` `        ``return` `tree[parent];` `    ``}` `    ``const mid = Math.floor((start + end) / 2);` `    ``const L = query(start, mid, 2 * parent + 1, qstart, qend, tree);` `    ``const R = query(mid + 1, end, 2 * parent + 2, qstart, qend, tree);` `    ``return` `L + R;` `}`   `function` `getSubsCount(S) {` `    ``const n = S.length;` `    ``const tree = Array.from({length: 4 * 2 * n + 1}, () => 0);`   `    ``const shift = n;` `    ``let currSum = 0;` `    ``let cnt = 0;`   `    ``update(0, 2 * n, 0, 0 + shift, tree);`   `    ``for` `(let i = 0; i < n; i++) {` `        ``currSum += (S.charAt(i) == ``'1'` `? 1 : -1);`   `        ``/*    prefix[j]-prefix[i]>=1` `            ``=> prefix[i]<=1-prefix[j]` `        ``*/`   `        ``const lessThan = Math.floor(currSum + shift) - 1;` `        ``cnt += query(0, 2 * n, 0, 0, lessThan, tree);`   `        ``update(0, 2 * n, 0, currSum + shift, tree);` `    ``}` `    ``return` `cnt;` `}`   `const input = ``"10011101"``;` `const ans = getSubsCount(input);` `console.log(ans);`

Output

```23

```

Time Complexity – O(NlogN) , O(logN) for query search in segment tree

Auxiliary Space – O(4*N)  ? O(N)

Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!

Previous
Next