imsuck's library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub imsuck/library

:warning: Static Range Query (ds/srq.hpp)

Description

Static Range Query (SRQ) solves offline range queries using divide and conquer. For each query [l, r), it computes op(v[l], v[l+1], ..., v[r-1]) where op is an associative operation.

Operations

Code

#pragma once

// https://usaco.guide/plat/DC-SRQ
// Not really optimized I just wrote this on a whim
template<class T, class Q, class Op> struct RangeQuery {
    RangeQuery(const vector<T> &v, const vector<Q> &_q, Op _op, T e) :
        ans((int)_q.size()), n((int)v.size()), d(v), lef(n, e), rig(n, e),
        idx((int)_q.size()), q(_q), op(_op) {
        iota(begin(idx), end(idx), 0);
    }
    void solve() { _solve(0, n - 1, idx); }

    vector<T> ans;

  private:
    int n;
    vector<T> d, lef, rig;
    vector<int> idx;
    vector<Q> q;
    Op op;
    void _solve(int l, int r, vector<int> &qry) {
        if (qry.empty()) return;
        if (l == r) {
            for (int &i : qry) ans[i] = d[l];
            return;
        }
        int m = (l + r) / 2;
        lef[m] = d[m];
        for (int i = m - 1; i >= l; i--) lef[i] = op(d[i], lef[i + 1]);
        rig[m + 1] = d[m + 1];
        for (int i = m + 2; i < r + 1; i++) rig[i] = op(rig[i - 1], d[i]);
        vector<int> le, ri;
        for (int i : qry) {
            if (q[i].l <= m && m < q[i].r) {
                ans[i] = op(lef[q[i].l], rig[q[i].r]);
                continue;
            }
            (q[i].l <= m ? le : ri).push_back(i);
        }
        _solve(l, m, le);
        _solve(m + 1, r, ri);
    }
};
template<class T, class Q, class Op>
auto make_rq(const vector<T> &v, const vector<Q> &q, Op op, T e) {
    return RangeQuery<T, Q, Op>{v, q, op, e};
}
#line 2 "ds/srq.hpp"

// https://usaco.guide/plat/DC-SRQ
// Not really optimized I just wrote this on a whim
template<class T, class Q, class Op> struct RangeQuery {
    RangeQuery(const vector<T> &v, const vector<Q> &_q, Op _op, T e) :
        ans((int)_q.size()), n((int)v.size()), d(v), lef(n, e), rig(n, e),
        idx((int)_q.size()), q(_q), op(_op) {
        iota(begin(idx), end(idx), 0);
    }
    void solve() { _solve(0, n - 1, idx); }

    vector<T> ans;

  private:
    int n;
    vector<T> d, lef, rig;
    vector<int> idx;
    vector<Q> q;
    Op op;
    void _solve(int l, int r, vector<int> &qry) {
        if (qry.empty()) return;
        if (l == r) {
            for (int &i : qry) ans[i] = d[l];
            return;
        }
        int m = (l + r) / 2;
        lef[m] = d[m];
        for (int i = m - 1; i >= l; i--) lef[i] = op(d[i], lef[i + 1]);
        rig[m + 1] = d[m + 1];
        for (int i = m + 2; i < r + 1; i++) rig[i] = op(rig[i - 1], d[i]);
        vector<int> le, ri;
        for (int i : qry) {
            if (q[i].l <= m && m < q[i].r) {
                ans[i] = op(lef[q[i].l], rig[q[i].r]);
                continue;
            }
            (q[i].l <= m ? le : ri).push_back(i);
        }
        _solve(l, m, le);
        _solve(m + 1, r, ri);
    }
};
template<class T, class Q, class Op>
auto make_rq(const vector<T> &v, const vector<Q> &q, Op op, T e) {
    return RangeQuery<T, Q, Op>{v, q, op, e};
}
Back to top page