Submission #1349697

#TimeUsernameProblemLanguageResultExecution timeMemory
1349697samman_varshneySum Zero (RMI20_sumzero)C++20
0 / 100
2 ms836 KiB
#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

// 2^19 is enough for N = 400,000
const int LOG = 19;

void solve() {
    int n;
    if (!(cin >> n)) return;

    vector<long long> p(n + 1, 0);
    vector<long long> coords;
    coords.push_back(0);
    
    for (int i = 1; i <= n; i++) {
        long long val;
        cin >> val;
        p[i] = p[i - 1] + val;
        coords.push_back(p[i]);
    }

    // Coordinate compression for fast prefix sum lookup
    sort(coords.begin(), coords.end());
    coords.erase(unique(coords.begin(), coords.end()), coords.end());
    auto get_id = [&](long long x) {
        return lower_bound(coords.begin(), coords.end(), x) - coords.begin();
    };

    // next_occ[i] = smallest j > i such that p[j] == p[i]
    vector<int> next_occ(n + 1, n + 1);
    vector<int> last_seen(coords.size(), -1);
    for (int i = n; i >= 0; i--) {
        int id = get_id(p[i]);
        if (last_seen[id] != -1) {
            next_occ[i] = last_seen[id];
        }
        last_seen[id] = i;
    }

    // min_end[i] = minimum end-index of any zero-sum subarray fully contained in [i, n]
    vector<int> min_end(n + 2, n + 1);
    for (int i = n; i >= 1; i--) {
        min_end[i] = min_end[i + 1];
        // Subarray starting at index i ends at next_occ[i-1]
        if (next_occ[i - 1] <= n) {
            min_end[i] = min(min_end[i], next_occ[i - 1]);
        }
    }

    // Binary Lifting table
    // up[0][i] is the next available starting position after one sum-0 subarray
    vector<vector<int>> up(LOG, vector<int>(n + 2, n + 1));
    for (int i = 1; i <= n; i++) {
        if (min_end[i] <= n) {
            up[0][i] = min_end[i] + 1;
        } else {
            up[0][i] = n + 1;
        }
    }

    // Build the sparse table
    for (int k = 1; k < LOG; k++) {
        for (int i = 1; i <= n + 1; i++) {
            up[k][i] = up[k - 1][up[k - 1][i]];
        }
    }

    int q;
    cin >> q;
    while (q--) {
        int l, r;
        cin >> l >> r;
        int count = 0;
        int curr = l;

        // Binary jump through disjoint subarrays
        for (int k = LOG - 1; k >= 0; k--) {
            // If the jump stays within the query boundary r
            if (up[k][curr] <= r + 1) {
                count += (1 << k);
                curr = up[k][curr];
            }
        }
        cout << count << "\n";
    }
}

int main() {
    // Fast I/O is critical for 400k constraints
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...