제출 #1328439

#제출 시각아이디문제언어결과실행 시간메모리
1328439Mauricio_CruzExhibition (JOI19_ho_t2)C++20
0 / 100
0 ms344 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct SegTree {
    int n;
    vector<int> st;
    SegTree() { n = 0; }
    SegTree(int _n) { init(_n); }
    void init(int _n) {
        n = 1;
        while (n < _n) n <<= 1;
        st.assign(2*n, 0);
    }
    // add v at position p (0-based)
    void add(int p, int v) {
        p += n;
        st[p] += v;
        p >>= 1;
        while (p) {
            st[p] = st[p<<1] + st[p<<1|1];
            p >>= 1;
        }
    }
    // query sum on [l,r] inclusive
    int sum_range(int l, int r) {
        if (l > r) return 0;
        l += n; r += n;
        int res = 0;
        while (l <= r) {
            if (l & 1) res += st[l++];
            if (!(r & 1)) res += st[r--];
            l >>= 1; r >>= 1;
        }
        return res;
    }
    // find first index >= ql with count > 0, or -1 if none
    int find_first_ge(int ql) {
        if (ql >= n) return -1;
        // if no elements in [ql, n-1] return -1
        if (sum_range(ql, n-1) == 0) return -1;
        int node = 1, l = 0, r = n-1;
        // descend but skip left parts that are entirely before ql
        while (l != r) {
            int mid = (l + r) >> 1;
            int leftNode = node<<1;
            if (ql <= mid) {
                // left side may contain answer
                if (st[leftNode] > 0) {
                    node = leftNode;
                    r = mid;
                } else {
                    node = leftNode|1;
                    l = mid+1;
                }
            } else {
                // skip left entirely
                node = leftNode|1;
                l = mid+1;
            }
        }
        return (l < n) ? l : -1;
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int N, M;
    if (!(cin >> N >> M)) return 0;
    vector<pair<ll,ll>> pics(N); // (value, size)
    for (int i = 0; i < N; ++i) {
        ll S, V; cin >> S >> V;
        pics[i] = {V, S};
    }
    vector<ll> frames(M);
    for (int j = 0; j < M; ++j) cin >> frames[j];

    // ordenar imágenes por valor asc, y para igual valor por tamaño desc
    sort(pics.begin(), pics.end(), [](const pair<ll,ll>& a, const pair<ll,ll>& b){
        if (a.first != b.first) return a.first < b.first;
        return a.second > b.second;
    });

    // compresión de tamaños (tanto de imágenes como de marcos)
    vector<ll> all;
    all.reserve(N + M);
    for (auto &pv : pics) all.push_back(pv.second);
    for (ll c : frames) all.push_back(c);
    sort(all.begin(), all.end());
    all.erase(unique(all.begin(), all.end()), all.end());
    auto comp = [&](ll x)->int {
        return int(lower_bound(all.begin(), all.end(), x) - all.begin());
    };
    int C = (int)all.size();
    // construir segment tree con conteos de marcos por tamaño comprimido
    SegTree st(C);
    for (ll c : frames) {
        int idx = comp(c);
        st.add(idx, 1);
    }

    int ans = 0;
    for (auto &pv : pics) {
        ll need_size = pv.second;
        int need_idx = comp(need_size);
        // buscamos primer índice >= need_idx con count>0
        int pos = st.find_first_ge(need_idx);
        if (pos != -1 && pos < C) {
            // asignar ese marco (decrementar)
            st.add(pos, -1);
            ++ans;
        }
    }

    cout << ans << "\n";
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...