Cod sursa(job #2850752)

Utilizator ArdeleanOficialAlexandru ArdeleanOficial Data 17 februarie 2022 15:07:25
Problema A+B Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 6.24 kb
#include <iostream>
#include <vector>

using namespace std;

const long long N = 2e5 + 7, B = 30, INF = 1e16 + 7;

long long a[N];

long long n;

namespace Aint {
    struct Nod {
        pair < long long, long long > minim;
        long long sum;

        Nod() {
            minim = {INF, INF};
            sum = 0;
        }
    } t[B][2 * N];

    long long b, poz, val, l, r;

    void Update(long long nod = 1, long long st = 1, long long dr = n) {
        if (st == dr) {
            t[b][nod].minim.first = t[b][nod].sum = val;
            t[b][nod].minim.second = INF;
            return;
        }
        long long mij((st + dr) >> 1);
        if (poz <= mij)
            Update(nod << 1, st, mij);
        else
            Update((nod << 1) + 1, mij + 1, dr);
        t[b][nod].minim.first = min(t[b][nod << 1].minim.first, t[b][(nod << 1) + 1].minim.first);
        t[b][nod].minim.second = min(t[b][nod << 1].minim.first + t[b][(nod << 1) + 1].minim.first - t[b][nod].minim.first, min(t[b][nod << 1].minim.second, t[b][(nod << 1) + 1].minim.second));
        t[b][nod].sum = t[b][nod << 1].sum + t[b][(nod << 1) + 1].sum;
    }

    void update(long long _b, long long _poz, long long _val) {
        b = _b;
        poz = _poz;
        val = _val;
        Update();
    }

    pair < pair < long long, long long >, long long > Query(long long nod = 1, long long st = 1, long long dr = n) {
        if (l <= st && dr <= r)
            return {t[b][nod].minim, t[b][nod].sum};
        long long mij((st + dr) >> 1);
        pair < pair < long long, long long >, long long > ans({INF, INF}, 0);
        if (l <= mij)
            ans = Query(nod << 1, st, mij);
        if (r > mij) {
            auto x = Query((nod << 1) + 1, mij + 1, dr);
            ans.first.first = min(ans.first.first, x.first.first);
            ans.first.second = min(ans.first.first + x.first.first - ans.first.first, min(ans.first.second, x.first.second));
            ans.second += x.second;
        }
        return ans;
    }

    pair < pair < long long, long long >, long long > query(long long _l, long long _r, long long _b) {
        l = _l;
        r = _r;
        b = _b;
        return Query();
    }

};

namespace MST {
    vector < long long > t[2 * N];

    void dfs(long long nod = 1, long long st = 1, long long dr = n) {
        if (st == dr) {
            t[nod] = {a[st]};
            return;
        }
        long long mij((st + dr) >> 1);
        dfs(nod << 1, st, mij);
        dfs((nod << 1) + 1, mij + 1, dr);
        long long i(0), j(0);
        while (i < t[nod << 1].size() && j < t[(nod << 1) + 1].size()) {
            if (t[nod << 1][i] < t[(nod << 1) + 1][j])
                t[nod].push_back(t[nod << 1][i++]);
            else
                t[nod].push_back(t[(nod << 1) + 1][j++]);
        }
        while (i < t[nod << 1].size())
            t[nod].push_back(t[nod << 1][i++]);
        while (j < t[(nod << 1) + 1].size())
            t[nod].push_back(t[(nod << 1) + 1][j++]);
    }

    long long l, r, val;

    long long small(long long nod = 1, long long st = 1, long long dr = n) {
        if (l <= st && dr <= r) {
            ///trebuie sa caut cati sunt mai mici
            long long pas = (1<<17), a(0);
            while (pas) {
                if (a + pas < t[nod].size() && t[nod][a + pas] < val)
                    a += pas;
                pas >>= 1;
            }
            if (t[nod][a] < val)
                return a + 1;
            return 0;
        }
        long long mij((st + dr) >> 1), ans(0);
        if (l <= mij)
            ans += small(nod << 1, st, mij);
        if (r > mij)
            ans += small((nod << 1) + 1, mij + 1, dr);
        return ans;
    }

    long long cauta(long long _l, long long _r, long long smaller) {
        l = _l;
        r = _r;
        long long pas = (1<<29), a(0);
        while (pas) {
            val = a + pas;
            if (small() <= smaller)
                a += pas;
            pas >>= 1;
        }
        return a;
    }
}

using namespace Aint;

bool check(long long val, long long l, long long r, long long k) {
    long long myb(0);
    long long sum(0);
    for (long long bit = 29; bit >= 0; --bit) {
        if (val & (1<<bit)) {
            myb = bit;
            break;
        }
    }
    for (long long bit = 0; bit < 30; ++bit) {///daca pot sa il fac pe cel mai mic din grupa, pot sa ii fac pe toti
        auto x = query(l, r, bit);
        if (bit == myb) {
            long long minim(x.first.first);
            if (minim == val)
                minim = x.first.second;
            if (val + sum < k + (minim == INF ? 0 : x.first.first))
                return 0;
            sum += x.second - val;
        }
        else {
            if (val + sum < k + (x.first.first == INF ? 0 : x.first.first))
                return 0;
            sum += x.second;
        }
    }
    return 1;
}

int main()
{
    long long q;
    bool cresc(1);
    cin >> n >> q;
    for (long long i = 1; i <= n; ++i) {
        cin >> a[i], cresc &= (i == 1 || a[i] >= a[i - 1]);
        long long b(0);
        for (long long bit = 29; bit >= 0; --bit) {
            if (a[i] & (1<<bit)) {
                b = bit;
                break;
            }
        }
        update(b, i, a[i]);
    }

    MST::dfs();

    while (q--) {
        long long l, r, k;
        cin >> l >> r >> k;
//        if (cresc) {
//            ///hbn
//            continue;
//        }
        long long pas(1<<17), a(0);
        while (pas) {
            if (a + pas + l <= r && !check(MST::cauta(l, r, a + pas), l, r, k))
                a += pas;
//            if (a + pas + l <= r) {
//                long long wow = MST::cauta(l, r, a + pas);
//                cout << "wow " << a + pas << ": " << wow << "\n";
//                if (!check(MST::cauta(l, r, a + pas), l, r, k))
//                    a += pas;
//            }
            pas >>= 1;
        }
        if (check(MST::cauta(l, r, a), l, r, k))
            a--;
        cout << r - l - a << '\n';
    }
    return 0;
}
/**
6 4
1000000003 1000000001 1000000005 1000000003 1000000007 1000000005
1 6 2
4 6 4
1 4 3
2 3 5


*/