Help needed to solve this "Queries for Decimal Values of Binary Subarrays" problem.

Hi all, I have been working on this problem "Queries for Decimal Values of Binary Subarrays" for more than 12 hours and it still won't pass the last hidden dataset. I really wanna solve this problem so I am reaching out for possible help here. Thank you for your time reading this!

The problem is posted on another OJ (glider.ai).
The link of it: https://app.glider.ai/practice/problem/basic-programming/queries-for-decimal-values-of-binary-subarrays/problem
The description is as follows:

Queries for Decimal Values of Binary Subarrays
For a given binary array with size of N, find the number represented by the subarray of a queried range.

Input:
The first line contains two space separated integers N and Q, where Q is number of queries.
The second line contains N space separated binary integers.
The next Q lines contains two space separated integers L and R and ranges of subarrays

Output:
Decimal value of queried subarray.

Constraints
(1 <= N <= 10^6)

Example#1
Input
5
2
1 0 1 1 0
0 2
2 4
Output
5
6
Explanation: The first subarray is {1 0 1} and decimal value of 101 is 5, the second subarray is {1 1 0} and decimal value of 110 is 6

Example#2
Input
4
1
1 0 0 0
0 3
Output
8
Explanation: Decimal value of 1000 is 8

Note that 1 <= N <= 10^6, I used two methods to solve it: 1. Mo's algorithm (sqrt decomposition); 2. Dividing N into several 63-size blocks (for long long type to store pre-computed values), which are attached here for reference. They both passed all test sets but the last one. Sadly, the failed one is hidden.

  1. Mo's algorithm. (https://www.hackerearth.com/zh/practice/notes/mos-algorithm/)
// Use Mo's algorithm to solve "Queries for Decimal Values of Binary Subarrays" problem
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

ll find_highest_bit(ll val) {
    ll res = 0;
    while (val > 0) {
        res = val;
        val &= (val - 1);
    }
    return res;
}

ll remove_r (int index, ll oldVal, const vector<int>& arr) {
    return (oldVal >> 1);
}

ll add_r (int index, ll oldVal, const vector<int>& arr) {
    return (oldVal << 1) + arr[index];
}

ll remove_l (int index, ll oldVal, const vector<int>& arr) {
    return oldVal - (arr[index] == 1 ? find_highest_bit(oldVal) : 0);
}

ll add_l (int index, ll oldVal, const vector<int>& arr) {
    return oldVal + ( arr[index] == 1 ? (find_highest_bit(oldVal) << 1) : 0 );
}

int main() {

    int N, Q;
    cin >> N >> Q;
    vector<int> A(N, 0);
    for (int i = 0; i < N; i++) cin >> A[i];
    vector<pair<pii, int> > queries;       //< <L, R>, 'indexes of input' >
    for (int i = 0; i < Q; i++) {
        int l, r;
        cin >> l >> r;
        queries.emplace_back(make_pair(make_pair(l,r), i));
    }

    sort (queries.begin(), queries.end(), [&](const auto& a, const auto& b) {
        return a.first.first != b.first.first ? a.first.first < b.first.first : a.first.second < b.first.second;
    });

    vector<ll> res (queries.size(), 0);
    int mo_left = 0, mo_right = -1;
    ll curr_result = 0;
    for (auto & querie : queries) {
        int left = querie.first.first, right = querie.first.second;

        while (mo_right < right) {
            mo_right++;
            curr_result = add_r(mo_right, curr_result, A);
        }

        while (mo_right > right) {
            curr_result = remove_r(mo_right, curr_result, A);
            mo_right--;
        }

        while (mo_left < left) {
            curr_result = remove_l(mo_left, curr_result, A);
            mo_left++;
        }

        while (mo_left > left) {
            mo_left--;
            curr_result = add_l(mo_left, curr_result, A);
        }

        res[querie.second] = curr_result;
    }

    for (auto n : res) {
        cout << n << endl;
    }

    return 0;
}
  1. Divide by size = 63 blocks.
// Use pre[BLOCK_NUM][BLOCK_SIZE=63] to solve "Queries for Decimal Values of Binary Subarrays" problem
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>

using namespace std;

typedef long long ll;

int main() {

    int N, Q;
    cin >> N >> Q;
    vector<int> A(N, 0);
    for (int i = 0; i < N; i++) cin >> A[i];

    //pre compute
    int BLOCK_SIZE = 63, BLOCK_NUM = (N - 1) / BLOCK_SIZE + 1;

    vector<int> block_left;
    for (int i = 0; i < N; i += BLOCK_SIZE) block_left.push_back(i);

    vector<vector<ll>> preSum (BLOCK_NUM, vector<ll>(BLOCK_SIZE, 0));
    for (int i = 0; i < block_left.size(); i++) {
        int l = block_left[i];
        for (ll r = min(l + BLOCK_SIZE - 1, N - 1), base = 1, prev = 0; r >= l; r--, base *= 2) {
            preSum[i][r-l] = prev + A[r]*base;
            prev = preSum[i][r-l];
        }
    }

    int L, R;
    while (cin >> L >> R) {
        auto it = upper_bound(block_left.begin(), block_left.end(), L) - 1;

        int left_margin_index = it - block_left.begin();
        ll res = 0;
        while (left_margin_index < block_left.size() && block_left[left_margin_index] <= R) {
            int left_margin = block_left[left_margin_index];
            int right_margin = min(left_margin_index + BLOCK_SIZE - 1, N - 1);
            int left = max(L, left_margin);
            int right = min(R, right_margin);

            res <<= (right - left + 1);
            ll to_minus = (right == right_margin ? 0 : preSum[left_margin_index][right - left_margin + 1]);
            res += ( (preSum[left_margin_index][left - left_margin] - to_minus) >> (right_margin - right) );
            left_margin_index++;
        }
        
        //if ( (res - 1)/2 == INT_MAX) res = INT_MIN;

        cout << res << endl;
    }

    return 0;
}

I really want to solve this problem! So any kind of help is appreciated! And I will share solutions once I have solved it.

Comments (1)