Codeforces Round #377 (Div. 2)D(二分)

时间:2023-11-24 22:31:08

题目链接:http://codeforces.com/contest/732/problem/D

题意:

在m天中要考k个课程,

数组a中有m个元素,表示第a[i]表示第i天可以进行哪门考试,若a[i]为0,则表示当天不能参加任何科目的考试,只能预习或者休息;

数组b中有k个元素,b[i]表示科目i需要复习几天才能通过;

问最快需要几天能通过所有考试,如果不能完成所有科目考试,输出-1;

思路:

用二分方法直接找满足条件的最小的数,其中数是指当前天是第几天,条件是指当前天以前是否能考完所有科目(包括当前天);

代码:

 #include <bits/stdc++.h>
#define MAXN 100000+10
using namespace std; int a[MAXN], b[MAXN], n, k; int gg(int x){ //××××××判断花费x天能否完成所有科目考试,即能否在第x天以前完成所有科目考试;
int cnt=, vis[MAXN];
memset(vis, , sizeof(vis));
for(int i=x; i>=; i--){
// cout << cnt << "//" << endl;
if(!a[i]){
cnt--;
cnt=max(cnt, );
}else if(!vis[a[i]]){
cnt+=b[a[i]-];
// cout << cnt << "***" << endl;
vis[a[i]]=;
if(cnt>i){
return ;
}
}else if(vis[a[i]]){
cnt--;
cnt=max(, cnt);
}
}
for(int i=; i<=k; i++){
if(!vis[i]){
return ;
}
}
return ;
} int main(void){
ios::sync_with_stdio(false), cin.tie(), cout.tie();
cin >> n >> k;
for(int i=; i<n; i++){
cin >> a[i];
}
for(int i=; i<k; i++){
cin >> b[i];
}
int l=, r=n;
while(l<r){ //××××××二分查找满足条件的最小数
int mid=(l+r)>>;
// cout << mid << " " << gg(mid) << endl;//****
if(gg(mid)){
r=mid;
}else{
l=mid+;
}
}
if(l>=n){
cout << "-1" << endl;
}else{
cout << l+ << endl;
}
return ;
}