제출 #1328437

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

#define fr(n) for(int i=0;i<n;i++)

int n, m;

// segment tree (max) storing indices (0-based) or -1
struct SegTree {
    int n;
    vector<int> st;
    SegTree(int _n=0){ init(_n); }
    void init(int _n){
        n = _n;
        st.assign(4*n, -1);
    }
    void upd(int p, int val){ upd(1,0,n-1,p,val); }
    void upd(int node,int l,int r,int p,int val){
        if(l==r){ st[node]=max(st[node], val); return; }
        int mid=(l+r)/2;
        if(p<=mid) upd(node*2,l,mid,p,val);
        else upd(node*2+1,mid+1,r,p,val);
        st[node]=max(st[node*2], st[node*2+1]);
    }
    int query(int L,int R){ 
        if(L>R) return -1;
        return query(1,0,n-1,L,R); 
    }
    int query(int node,int l,int r,int L,int R){
        if(R<l || r<L) return -1;
        if(L<=l && r<=R) return st[node];
        int mid=(l+r)/2;
        return max(query(node*2,l,mid,L,R), query(node*2+1,mid+1,r,L,R));
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    if(!(cin>>n>>m)) return 0;
    vector<pair<ll,ll>> v(n);
    for(int i=0;i<n;i++){
        ll x,y; cin>>x>>y;
        v[i] = {y,x}; // ordenar por y desc
    }
    sort(v.begin(), v.end(), greater<>());
    vector<ll> a(n);
    for(int i=0;i<n;i++) a[i] = v[i].second;
    vector<ll> p(m);
    for(int i=0;i<m;i++) cin>>p[i];

    // compresión: juntar a y p, ordenar asc y map a 0..c-1
    vector<ll> allv = a;
    allv.insert(allv.end(), p.begin(), p.end());
    sort(allv.begin(), allv.end());
    allv.erase(unique(allv.begin(), allv.end()), allv.end());
    int c = (int)allv.size();
    auto comp = [&](ll x){ return (int)(lower_bound(allv.begin(), allv.end(), x) - allv.begin()); };

    for(int i=0;i<n;i++) a[i] = comp(a[i]);
    for(int i=0;i<m;i++) p[i] = comp(p[i]);

    // p_val: p ordenado en orden descendente (valores comprimidos)
    vector<int> p_val(m);
    for(int i=0;i<m;i++) p_val[i] = (int)p[i];
    sort(p_val.begin(), p_val.end(), greater<int>());

    // segment tree sobre rango de valores comprimidos [0..c-1]
    SegTree st(c);

    int res = 0;
    // recorremos a (ya ordenado por y desc)
    for(int i=0;i<n && res < m;i++){
        int ai = (int)a[i]; // valor comprimido en [0..c-1]

        // buscamos en p_val el mayor índice j tal que p_val[j] >= ai
        // p_val es descendente, queremos el rightmost index with p_val[j] >= ai
        int lo = 0, hi = m-1, pos = -1;
        while(lo <= hi){
            int mid = (lo + hi) >> 1;
            if(p_val[mid] >= ai){
                pos = mid;
                lo = mid + 1;
            } else hi = mid - 1;
        }
        if(pos == -1) continue; // no hay p >= ai

        // consultamos el árbol en el rango [ai, c-1] para obtener el mejor índice ya guardado
        int q = st.query(ai, c-1); // q es índice 0-based en p_val o -1
        // si no hay nada guardado, podemos usar pos (el mejor disponible)
        int useIdx = max(q, pos);
        // pero solo actualizamos si p_val[useIdx] >= ai (debería ser cierto)
        if(useIdx != -1 && p_val[useIdx] >= ai){
            // guardamos useIdx en la posición ai (podemos guardar el mejor índice alcanzable desde ai)
            st.upd(ai, useIdx);
            res = max(res, useIdx + 1); // cantidad = índice+1
        }
    }

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