传送门:Exams
题意:有n天和m门考试,每场考试都需要一定的准备时间,每天可能能考其中一门也可能不能考试,问最短多少天能考完所有科目。
明显的贪心题目,当时想到了从后往前贪心,只是没想到用二分去做,还是太水啊。
#include <iostream>
#include <cstdio>
#include <cstring>
#define M 100005
using namespace std;
int test[M],time[M],book[M];
int sum=0;
int n,m;
int check(int x)
{
memset(book,0,sizeof(book));
int t=0;
for(int i=x;i>=1;i--)
{
if(test[i])
{
if(!book[test[i]])
{
book[test[i]]=1;
t+=time[test[i]];
}
else
if(t>0)
t--;
}
else
if(t>0)
t--;
}
for(int i=1;i<=m;i++)
if(!book[i])//注意这里如果有考试没出现过的话肯定不行
return 0;
if(t<=0)//这里t可以为负数
return 1;
return 0;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
int flag=0;
sum=0;
for(int i=1;i<=n;i++)
scanf("%d",&test[i]);
for(int i=1;i<=m;i++)
{
scanf("%d",&time[i]);
sum+=time[i];
}
int l=1,r=n;
int mid=(l+r)/2;
while(l<=r)//注意这里循环条件为小于等于,否则有可能出现“r没动过,一直是l变,flag就一直为零,输出为-1
{<span style="white-space:pre"> </span>//其实n为正确答案”的情况,如果l<r为循环条件会使这种情况输出-1,解决办法就是让程序多判断一遍使flag=1就好了
if(check(mid))//另外还有解决办法就是循环条件为l<r,然后单独check一下n。
{
r=mid-1;
flag=1;
}
else
l=mid+1;
mid=(l+r)/2;
}
if(flag)
printf("%d\n",l);
else
printf("-1\n");
}
return 0;
}