题目连接:http://codeforces.com/problemset/problem/732/D
题意:n天,m个考试,n天中的每一天,0代表该天不能考试,其他表示能考哪一门试。m个考试科目每科都有一定的准备时间,准备完了才能考,但不用连续准备。任意一非0的天可以选择考试或者准备考试,问在n天内完成所有科目所花的最少天数,如果不能考完,则输出-1。
二分+贪心。二分枚举天数,根据能否复习完去更新左右端点。 贪心就是要从最后一天往前贪心,第一次遇到科目就准备,能都准备完就满足。
#include <bits/stdc++.h>
using namespace std;
int d[100100], a[100100];
int prep[100100], n, m;
bool check(int k) {
memset(prep, 0, sizeof(prep));
int need = 0;
for(int i = k; i > 0; i--) {
if(d[i] && !prep[d[i]]) {
prep[d[i]] = 1;
need += a[d[i]];
}
else if(need > 0) need--;
}
int i;
for(i = 1; i <= m; i++) {
if(prep[i] == 0) break;
}
if(i != m + 1 || need) return false;
return true;
}
int main() {
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++) {
scanf("%d", d + i);
}
for(int i = 1; i <= m; i++) {
scanf("%d", a + i);
}
int l = 1, r = n;
while(l <= r) {
int m = (r + l) / 2;
if(check(m) == true) r = m - 1;
else l = m + 1;
}
if(check(r)) printf("%d", r);
else if(check(l)) printf("%d", l);
else puts("-1");
return 0;
}