제출 #1357646

#제출 시각아이디문제언어결과실행 시간메모리
1357646domiGrowing Trees (BOI11_grow)C++20
100 / 100
458 ms5824 KiB
#include <bits/stdc++.h>

#define int long long
#define fi first
#define se second

#define sz(a) (int)((a).size())
#define all(a) (a).begin(), (a).end()

#define lsb(x) (x & (-x))
#define vi vector<int>
#define YES { cout << "YES" << endl; return; }
#define NO { cout << "NO" << endl; return; }

using ll = long long;
using pii = std::pair<int, int>;

const int NMAX = 1e5;

using namespace std;

char ch;
int a[NMAX + 5], n, q;

struct LazySeg {
    int aint[4 * NMAX + 5];
    int lazy[4 * NMAX + 5];

    void build(int nod = 1, int st = 1, int dr = n) {
        if (st == dr) {
            aint[nod] = a[st];
            return;
        }

        int m = (st + dr) >> 1;
        build(2 * nod, st, m);
        build(2 * nod + 1, m + 1, dr);
        aint[nod] = aint[2 * nod] + aint[2 * nod + 1];
    }

    void push(int nod, int st, int dr) {
        if (lazy[nod] != 0) {
            aint[nod] += (dr - st + 1) * lazy[nod];
            if (st != dr) {
                lazy[2 * nod] += lazy[nod];
                lazy[2 * nod + 1] += lazy[nod];
            }
            lazy[nod] = 0;
        }
    }

    void range_add(int l, int r, int v, int nod = 1, int st = 1, int dr = n) {
        push(nod, st, dr);

        if (st > r || dr < l) return;
        if (l <= st && dr <= r) {
            lazy[nod] += v;
            push(nod, st, dr);
            return;
        }

        int m = (st + dr) >> 1;
        range_add(l, r, v, 2 * nod, st, m);
        range_add(l, r, v, 2 * nod + 1, m + 1, dr);
        aint[nod] = aint[2 * nod] + aint[2 * nod + 1];
    }

    int query(int l, int r, int nod = 1, int st = 1, int dr = n) {
        push(nod, st, dr);
        if (st > r || dr < l) return 0;
        if (l <= st && dr <= r) return aint[nod];

        int m = (st + dr) >> 1;
        return query(l, r, 2 * nod, st, m) + query(l, r, 2 * nod + 1, m + 1, dr);
    }
};
LazySeg aint;

///first element >= x
int find_first(int x) {
    int lo = 1, hi = n, idx = -1;
    while (lo <= hi) {
        auto mid = (lo + hi) >> 1;

        if (aint.query(mid, mid) >= x) {
            idx = mid;
            hi = mid - 1;
        }
        else
            lo = mid + 1;
    }

    return idx;
}

/// last element <= x
int find_last(int x) {
    int lo = 1, hi = n, idx = -1;
    while (lo <= hi) {
        auto mid = (lo + hi) >> 1;

        if (aint.query(mid, mid) <= x) {
            idx = mid;
            lo = mid + 1;
        }
        else
            hi = mid - 1;
    }

    return idx;
}

signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    cin >> n >> q;

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

    sort(a + 1, a + n + 1);
    aint.build();
    for (int i = 0, k, h, mn, mx; i < q; ++i) {
        cin >> ch;

        if (ch == 'F') {
            cin >> k >> h;

            int L = find_first(h);
            if (L == -1) continue;
            int R = L + k - 1;

            if (R >= n) {
                aint.range_add(L, R, 1);
                continue;
            }

            int val = aint.query(R, R);
            int first_occ = find_first(val);
            int last_occ = find_last(val);
            int leftover = k - (first_occ - L);

            if (L <= first_occ - 1) aint.range_add(L, first_occ - 1, 1);
            aint.range_add(last_occ - leftover + 1, last_occ, 1);
        }


        if (ch == 'C') {
            cin >> mn >> mx;

            if (aint.query(1, 1) > mx || aint.query(n, n) < mn) {
                cout << "0\n";
                continue;
            }

            cout << (find_last(mx) - find_first(mn) + 1) << '\n';
        }
    }
    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…