CF732D Exams

這題能夠用二分答案來作ios

那麼爲何能夠用二分答案呢?git

答案固然是知足了單調性。 假設用\(x\)天可以考完全部試,那麼用大於$x $天一定也可以考完全部試,因此知足了單調性,咱們就能夠二分答案spa

那麼如何\(check\)呢?考慮一下貪心code

貪心思路:在二分的\(mid\)天以前找到每一科考試能夠考的最後一天,只在這一天去考這一門科目,其它時間積攢複習時間,若在\(mid\)前這個科目可考的最後一天出現了,而此時積攢的複習時間並不足以考過這門科目,則說明用\(mid\)天不能考完這些科目,不然就讓計數器\(cnt\)的值加一,表示如今已經考了\(cnt\)門,最後檢驗一下\(cnt\)是否等於\(m\),若不等於則說明還有科目在\(mid\)天前沒有出現,增大範圍,不然縮小範圍,讓\(ans\)等於\(mid\)get

代碼以下string

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int A = 1e5 + 11;
const int B = 1e6 + 11;

inline int read() {
    char c = getchar(); int x = 0, f = 1;
    for( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for( ; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48);
    return x * f;
}

int n, m, all, cnt;
int d[A], w[A], a[A], la[A];

inline bool check(int x) {
    memset(la, 0, sizeof(la));
    for(int i = 1; i <= n; i++) a[i] = d[i];
    for(int i = 1; i <= x; i++) if(a[i]) a[la[a[i]]] = 0, la[a[i]] = i; 
    int tl = 0, cnt = 0;
    for(int i = 1; i <= x; i++) {
        if(a[i]) { tl -= w[a[i]]; if(tl < 0) return 0; else cnt++; }
        else tl++;
    }
    return cnt == m; 
}

int main() {
    n = read(), m = read();
    if(n < m) return puts("-1"), 0;
    for(int i = 1; i <= n; i++) d[i] = read();
    for(int i = 1; i <= m; i++) w[i] = read(), all += w[i];
    if(all > n) return puts("-1"), 0;
    int l = 0, r = n, ans = -1;
    while(l <= r) {
        int mid = (l + r) >> 1;
        if(check(mid)) ans = mid, r = mid - 1;
        else l = mid + 1;
    }
    return cout << ans << '\n', 0;
}
本站公眾號
   歡迎關注本站公眾號,獲取更多信息