제출 #1328121

#제출 시각아이디문제언어결과실행 시간메모리
1328121model_codeExhibition 3 (JOI25_exhibition3)C++20
100 / 100
559 ms35728 KiB
// O(M(sqrt N + log M))
#include <bits/stdc++.h>

using namespace std;

class LazySegmentTree {
    using S = int;

    const S e = -1;

    S op(const S &l, const S &r) {
        return max(l, r);
    }

    using F = pair<bool, int>;

    const F id = {false, 0};

    F composition(const F &g, const F &f) {
        return (g.first ? g : f);
    }

    S mapping(const F &f, const S &x) {
        return (f.first ? f.second : x);
    }

    int n, log;
    vector<S> d;
    vector<F> lz;

    void update(int k) { d[k] = op(d[2 * k], d[2 * k + 1]); }

    void all_apply(int k, F f) {
        d[k] = mapping(f, d[k]);
        if (k < n) lz[k] = composition(f, lz[k]);
    }

    void push(int k) {
        all_apply(2 * k, lz[k]);
        all_apply(2 * k + 1, lz[k]);
        lz[k] = id;
    }

public:
    LazySegmentTree(int _n) {
        log = 0;
        while ((1 << log) < _n) log++;
        n = 1 << log;
        d.assign(2 * n, e);
        lz.assign(n, id);
    }

    S prod(int l, int r) {
        assert(0 <= l and l <= r and r <= n);

        l += n, r += n;

        for (int i = log; i >= 1; i--) {
            if ((l >> i) << i != l) push(l >> i);
            if ((r >> i) << i != r) push(r >> i);
        }

        S res = e;
        while (l < r) {
            if (l & 1) res = op(res, d[l++]);
            if (r & 1) res = op(res, d[--r]);
            l >>= 1, r >>= 1;
        }

        return res;
    }

    void apply(int l, int r, F f) {
        assert(0 <= l and l <= r and r <= n);

        l += n, r += n;

        for (int i = log; i >= 1; i--) {
            if ((l >> i) << i != l) push(l >> i);
            if ((r >> i) << i != r) push(r >> i);
        }

        {
            int l2 = l, r2 = r;
            while (l < r) {
                if (l & 1) all_apply(l++, f);
                if (r & 1) all_apply(--r, f);
                l >>= 1, r >>= 1;
            }
            l = l2, r = r2;
        }

        for (int i = 1; i <= log; i++) {
            if ((l >> i) << i != l) update(l >> i);
            if ((r >> i) << i != r) update(r >> i);
        }
    }
};

class IncrementalIntervalScheduling {
    int n, b, num;
    map<int, int> mp;
    vector<int> L, to, cnt;

    void update_block(int id) {
        assert(0 <= id and id < num);
        int l = id * b, r = (id + 1) * b;
        for (int i = r - 1; i >= l; i--) {
            int nx, g;
            if (L[i] == -1) {
                nx = i + 1, g = 0;
            } else {
                nx = L[i], g = 1;
            }
            if (nx < r) {
                to[i] = to[nx];
                cnt[i] = cnt[nx] + g;
            } else {
                to[i] = nx;
                cnt[i] = g;
            }
        }
    }

public:
    IncrementalIntervalScheduling(int n) : n(n) {
        b = clamp((int) sqrt(n), 1, n);
        num = (n + 1 + b - 1) / b;
        L.assign(b * num, -1);
        to.resize(b * num);
        cnt.resize(b * num);
        for (int i = 0; i < num; i++) update_block(i);
    }

    void reset() {
        for (auto [l, r]: mp) {
            L[l] = -1;
            update_block(l / b);
        }
        mp.clear();
    }

    void add(int l, int r) {
        assert(0 <= l and l < r and r <= n);
        auto it = mp.lower_bound(l);
        if (it == mp.end() or it->second > r) {
            mp[l] = r;
            L[l] = r;
            update_block(l / b);
            it = mp.find(l);
            while (it != mp.begin()) {
                --it;
                if (it->second < next(it)->second) break;
                L[it->first] = -1;
                update_block(it->first / b);
                it = mp.erase(it);
            }
        }
    }

    int interval_scheduling() {
        int now = 0, res = 0;
        while(now < n) {
            res += cnt[now];
            now = to[now];
        }
        return res;
    }
};

class IntervalManager {
    int n;
    vector<int> r_ls;
    map<int, int> mp;
public:
    vector<int> build(vector<pair<int, int>> ls, int _n) {
        n = _n;
        sort(ls.begin(), ls.end(), [](auto a, auto b) { return a.second < b.second; });
        int now = -(1 << 30);
        for (auto [l, r]: ls) {
            if (mp.contains(l)) mp[l] = min(mp[l], r);
            else mp[l] = r;
            if (now > l) continue;
            now = r;
            r_ls.push_back(r);
        }
        assert((int) r_ls.size() == n);
        if (mp.empty()) return r_ls;
        auto it = prev(mp.end());
        while (it != mp.begin()) {
            --it;
            if (it->second >= next(it)->second) {
                it = mp.erase(it);
            }
        }
        return r_ls;
    }

    // returns the list of pairs of (old_val, new_val)
    vector<pair<int, int>> add(int l, int r) {
        // update mp
        {
            auto it = mp.lower_bound(l);
            if (it == mp.end() or it->second > r) {
                mp[l] = r;
                it = mp.find(l);
                while (it != mp.begin()) {
                    --it;
                    if (it->second < next(it)->second) break;
                    it = mp.erase(it);
                }
            }
        }
        vector<pair<int, int>> res;
        // update r_ls
        {
            auto it = lower_bound(r_ls.begin(), r_ls.end(), r);
            while (it != r_ls.end()) {
                int lb = (it == r_ls.begin() ? -(1 << 30) : *prev(it));
                int nr = mp.lower_bound(lb)->second;
                assert(nr <= *it);
                if (nr == *it) break;
                res.emplace_back(*it, nr);
                *it = nr;
                it++;
            }
        }
        return res;
    }
};

int main() {
    int n, m;
    cin >> n >> m;
    vector<int> c(n);
    for (int i = 0; i < n; i++) {
        int a;
        cin >> a;
        ++c[--a];
    }
    IncrementalIntervalScheduling iis(n);
    int frontier = n - 1;
    LazySegmentTree st(n);
    vector<pair<int, int>> ls;
    vector<IntervalManager> lm(n), rm(n);
    while (m--) {
        int l, r;
        cin >> l >> r;
        --l;
        int mx = st.prod(l, r);
        if (mx == -1) {
            while (!c[frontier]) --frontier;
            cout << frontier + 1 << '\n';
            iis.add(l, r);
            ls.emplace_back(l, r);
            if (iis.interval_scheduling() == c[frontier]) {
                vector<int> nr = lm[frontier].build(ls, c[frontier]);
                for (int i = 0; i < (int) ls.size(); i++) {
                    auto [x, y] = ls[i];
                    ls[i] = {-y, -x};
                }
                vector<int> nl = rm[frontier].build(ls, c[frontier]);
                reverse(nl.begin(), nl.end());
                for (int &i: nl) i = -i;
                for (int i = 0; i < c[frontier]; i++) {
                    assert(nl[i] < nr[i]);
                    st.apply(nl[i], nr[i], {true, frontier});
                }
                ls.clear();
                iis.reset();
                --frontier;
            }
        } else {
            cout << mx + 1 << '\n';
            for (auto [pre, now]: lm[mx].add(l, r)) {
                st.apply(now, pre, {true, -1});
            }
            for (auto [pre, now]: rm[mx].add(-r, -l)) {
                st.apply(-pre, -now, {true, -1});
            }
        }
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...