Cerinta completa

You are given an array, , consisting of integers.

A segment, , is beautiful if and only if the bitwise AND of all numbers in with indices in the inclusive range of is not greater than . In other words, segment is beautiful if .

You must answer queries. Each query, , consists of integers: , , and . The answer for each is the number of beautiful segments such that and .

Input Format

The first line contains two space-separated integers, (the number of integers in ) and (the number of queries).

The second line contains space-separated integers, where the integer denotes the element of array .

Each line of the subsequent lines contains space-separated integers, , , and , respectively, describing query .

Constraints

  • holds for test cases worth at least of the problem’s score.
  • holds for test cases worth at least of the problem’s score.

Output Format

Print lines, where the line contains the number of beautiful segments for query .

Sample Input

5 3
1 2 7 3 4
1 5 3
2 4 6
3 5 2

Sample Output

13
5
2

Explanation

The beautiful segments for all queries are listed below.

Query 0: The beautiful segments are .

Query 1: The beautiful segments are .

Query 2: The beautiful segments are .


Limbajul de programare folosit: cpp14

Cod:

#include <bits/stdc++.h>
using namespace std;

struct Event {
    int v;
    int r;
    int a;
    int b;
};

struct PrefixQuery {
    int x;
    int t;
    int l;
    int id;
    int sign;
};

struct NodeData {
    vector<int> xs;
    vector<long long> bitSlope;
    vector<long long> bitConst;

    void init() {
        sort(xs.begin(), xs.end());
        xs.erase(unique(xs.begin(), xs.end()), xs.end());
        bitSlope.assign(xs.size() + 2, 0);
        bitConst.assign(xs.size() + 2, 0);
    }

    inline void bitAdd(vector<long long>& bit, int idx, long long delta) {
        int n = (int)bit.size() - 1;
        for (int i = idx; i <= n; i += i & -i) bit[i] += delta;
    }

    inline long long bitSum(const vector<long long>& bit, int idx) const {
        long long res = 0;
        for (int i = idx; i > 0; i -= i & -i) res += bit[i];
        return res;
    }

    void rangeAddLinear(int lVal, int rVal, long long slope, long long cst) {
        if (lVal > rVal || xs.empty()) return;
        int li = (int)(lower_bound(xs.begin(), xs.end(), lVal) - xs.begin()) + 1;
        int ri = (int)(upper_bound(xs.begin(), xs.end(), rVal) - xs.begin());
        if (li > ri) return;

        bitAdd(bitSlope, li, slope);
        bitAdd(bitSlope, ri + 1, -slope);
        bitAdd(bitConst, li, cst);
        bitAdd(bitConst, ri + 1, -cst);
    }

    long long pointQuery(int lVal) const {
        if (xs.empty()) return 0;
        int pos = (int)(lower_bound(xs.begin(), xs.end(), lVal) - xs.begin()) + 1;
        long long slope = bitSum(bitSlope, pos);
        long long cst = bitSum(bitConst, pos);
        return slope * lVal + cst;
    }
};

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

    int N, Q;
    cin >> N >> Q;

    vector<int> a(N + 1);
    for (int i = 1; i <= N; ++i) cin >> a[i];

    vector<tuple<int, int, int>> queries(Q);
    for (int i = 0; i < Q; ++i) {
        int l, r, x;
        cin >> l >> r >> x;
        queries[i] = {l, r, x};
    }

    vector<Event> events;
    events.reserve((size_t)N * 20);

    vector<pair<int, int>> prev;
    prev.reserve(20);

    for (int r = 1; r <= N; ++r) {
        vector<pair<int, int>> cur;
        cur.reserve(prev.size() + 1);
        cur.push_back({a[r], r});

        for (auto &p : prev) {
            int nv = p.first & a[r];
            if (cur.back().first == nv) {
                cur.back().second = p.second;
            } else {
                cur.push_back({nv, p.second});
            }
        }

        for (int j = 0; j < (int)cur.size(); ++j) {
            int v = cur[j].first;
            int lStart = cur[j].second;
            int lEnd = (j == 0 ? r : cur[j - 1].second - 1);
            events.push_back({v, r, lStart, lEnd});
        }

        prev.swap(cur);
    }

    vector<PrefixQuery> pref;
    pref.reserve(2 * Q);

    for (int i = 0; i < Q; ++i) {
        int l, r, x;
        tie(l, r, x) = queries[i];
        pref.push_back({x, r, l, i, +1});
        pref.push_back({x, l - 1, l, i, -1});
    }

    vector<NodeData> fw(N + 1);
    for (const auto& pq : pref) {
        int t = pq.t;
        while (t > 0) {
            fw[t].xs.push_back(pq.l);
            t -= t & -t;
        }
    }
    for (int i = 1; i <= N; ++i) fw[i].init();

    auto addEvent = [&](const Event& e) {
        int len = e.b - e.a + 1;
        for (int i = e.r; i <= N; i += i & -i) {
            // L in [1, a-1] => +len
            fw[i].rangeAddLinear(1, e.a - 1, 0, len);
            // L in [a, b] => (b+1)-L
            fw[i].rangeAddLinear(e.a, e.b, -1, e.b + 1);
        }
    };

    auto prefixQuery = [&](int t, int lVal) {
        long long res = 0;
        for (int i = t; i > 0; i -= i & -i) {
            res += fw[i].pointQuery(lVal);
        }
        return res;
    };

    sort(events.begin(), events.end(), [](const Event& A, const Event& B) {
        if (A.v != B.v) return A.v < B.v;
        if (A.r != B.r) return A.r < B.r;
        if (A.a != B.a) return A.a < B.a;
        return A.b < B.b;
    });

    sort(pref.begin(), pref.end(), [](const PrefixQuery& A, const PrefixQuery& B) {
        if (A.x != B.x) return A.x < B.x;
        return A.t < B.t;
    });

    vector<long long> ans(Q, 0);
    int ptr = 0;
    for (const auto& pq : pref) {
        while (ptr < (int)events.size() && events[ptr].v <= pq.x) {
            addEvent(events[ptr]);
            ++ptr;
        }
        long long cur = (pq.t > 0 ? prefixQuery(pq.t, pq.l) : 0);
        ans[pq.id] += (long long)pq.sign * cur;
    }

    for (int i = 0; i < Q; ++i) {
        cout << ans[i] << '\n';
    }

    return 0;
}

Scor obtinut: 1.0

Submission ID: 464672216

Link challenge: https://www.hackerrank.com/challenges/beautiful-segments/problem

Beautiful Segments