0w1

CFR 732 D. Exams ( Binary Search + Greedy )

Problem - D - Codeforces
二分搜答案,對於所有考試,一定考最後一個日期,這時候就變區間置點問題,所有考試對應一個區間,且在該區間必須放置 k 個點。
注意考試時不能讀書。

bool cmp( pii a, pii b ){
    if( a.first != b.first )
        return a.first > b.first;
    return a.second < b.second;
}

bool ok( vi d, vi a, int x ){
    set< int > vis;
    set< int > td;
    priority_queue< pii, vp, greater< pii > > pq;
    for( int i = x - 1; i >= 0; --i ){
        if( d[ i ] == 0 or vis.count( d[ i ] ) )
            continue;
        vis.insert( d[ i ] );
        td.insert( i );
        pq.push( pii( i, a[ d[ i ] - 1 ] ) );
        // cout << i << " " << a[ d[ i ] - 1 ] << endl;
    }
    if( vis.size() != a.size() )
        return false;
    for( int i = 0; i < x; ++i ){
        if( td.count( i ) )
            continue;
        if( pq.empty() )
            return true;
        int r = pq.top().first;
        int q = pq.top().second;
        pq.pop();
        // cout << i << r << q << endl;
        if( i >= r )
            return false;
        if( q - 1 > 0 )
            pq.push( pii( r, q - 1 ) );
    }
    return pq.empty();
}

void solve(){
    int N, M; cin >> N >> M;
    vi D( N );
    for( int i = 0; i < N; ++i )
        cin >> D[ i ];
    vi A( M );
    for( int i = 0; i < M; ++i )
        cin >> A[ i ];
    // cout << ok( D, A, 9 ) << endl; return;
    int lb = 1, rb = N;
    int ans = -1;
    while( lb <= rb ){
        int mid = lb + rb >> 1;
        if( ok( D, A, mid ) )
            ans = mid, rb = mid - 1;
        else
            lb = mid + 1;
    }
    cout << ans << endl;
}