Submission #1076387

#TimeUsernameProblemLanguageResultExecution timeMemory
1076387IdanRosenSum Zero (RMI20_sumzero)C++98
22 / 100
105 ms29504 KiB
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef std::pair<ll, ll> pii;
typedef std::pair<ll, ll> pll;
typedef std::pair<ld, ld> pld;

template<typename T, typename D>
class sparse_table {
private:
    size_t n;
    size_t logn;
    vector<vector<D> > table;
    vector<size_t> lg;

    D (*convert)(const T &);

    T (*function)(const T &, const T &);

public:
    sparse_table(const vector<T> &arr, D (*conv)(const T &), T (*func)(const T &, const T &)) : n(arr.size()),
        logn(log2(n) + 1),
        convert(conv), function(func) {
        table.resize(logn, vector<T>(n));
        for (size_t i = 0; i < n; i++)
            table[0][i] = convert(arr[i]);

        for (size_t k = 1; k < logn; k++)
            for (size_t i = 0; i + (1 << k) <= n; i++)
                table[k][i] = function(table[k - 1][i], table[k - 1][i + (1 << (k - 1))]);

        // lg[i] stores and biggest i such that
        // 2^i is smaller or equal to i
        lg.resize(n + 1);
        for (size_t i = 1; i <= n; i++)
            lg[i] = (1 + log2(i)) - 1;
    }

    // query that merges two (may) overlapping ranges
    T query_overlap(size_t l, size_t r) {
        // [l, r)
        size_t pow = lg[r - l];

        return function(
            table[pow][l],
            table[pow][r - (1 << pow)]
        );
    }

    // qeury that merges non overlapping ranges
    T query_nooverlap(size_t l, size_t r) {
        // [l, r)
        bool empty = true;
        T ans;

        size_t curr_l = l;
        for (ssize_t k = logn - 1; k >= 0; k--) {
            size_t sz = 1 << k;

            if (sz <= r - curr_l) {
                if (empty) {
                    ans = table[k][curr_l];
                    empty = false;
                } else
                    ans = function(ans, table[k][curr_l]);

                curr_l += sz;
            }
        }

        return ans;
    }
};


int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);

    ll n;
    cin >> n;

    vector<ll> arr(n);
    for (auto &i: arr) cin >> i;

    map<ll, set<ll> > sums;
    vector<ll> pre_sum(n + 1);
    pre_sum[0] = 0;
    for (ll i = 0; i < n; i++) {
        pre_sum[i + 1] = pre_sum[i] + arr[i];
        sums[pre_sum[i + 1]].insert(i + 1);
    }

    vector<ll> next(n, LLONG_MAX);
    ll curr_sum = 0;
    for (ll i = 0; i < n; i++) {
        if (sums.count(curr_sum)) {
            auto it = sums[curr_sum].upper_bound(i);
            if (it != sums[curr_sum].end()) next[i] = *it;
        }
        curr_sum += arr[i];
    }

    for (ll i = n - 2; i >= 0; i--)
        next[i] = min(next[i], next[i + 1]);

    ll logn = log2(n) + 1;
    vector<vector<ll> > jump(n, vector<ll>(logn));
    for (ll i = 0; i < n; i++) jump[i][0] = next[i];
    for (ll k = 1; k < logn; k++)
        for (ll i = 0; i < n; i++)
            jump[i][k] = ((jump[i][k - 1] == LLONG_MAX || jump[i][k - 1] == n) ? LLONG_MAX : jump[jump[i][k - 1]][k - 1]);

    ll q;
    cin >> q;
    while (q-- > 0) {
        ll l, r;
        cin >> l >> r;
        --l;

        ll ans = 0;
        ll curr = l;
        for (ll k = logn - 1; k >= 0 && curr < n; k--) {
            if (jump[curr][k] <= r) {
                curr = jump[curr][k];
                ans += pow(2, k);
            }
        }

        cout << ans << "\n";
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...