【CF732D】Exams(线性扫描,贪心,二分)

时间:2021-11-10 21:04:18

题意:有m门需要过的课程,n天的时间可以选择复习、考试(如果的d[i]为0则只能复习),一门课至少要复习a[i]天才能通过(可以不连续的复习得到a[i]),问最早什么时候可以把所有课程都通过,如果不能输出-1。

1 ≤ n, m ≤ 10^5) 

思路:贪心思想可知每门课尽可能拖到最后考是最优方案,这样复习的天数就最多

        二分答案验证是否可行,每考一门课就把复习的总日数减去

 1 var a,b,c,d:array[1..110000]of longint;
 2     n,m,l,r,mid,last,i:longint;
 3 
 4 function isok(len:longint):boolean;
 5 var i,s:longint;
 6 begin
 7  fillchar(b,sizeof(b),0);
 8  fillchar(c,sizeof(c),0);
 9  for i:=len downto 1 do
10   if (a[i]>0)and(c[a[i]]=0) then
11   begin
12    b[i]:=a[i];
13    c[a[i]]:=1;
14   end;
15  s:=0;
16  for i:=1 to len do
17   if b[i]=0 then inc(s)
18    else
19    begin
20     if d[b[i]]>s then exit(false)
21      else s:=s-d[b[i]];
22    end;
23  for i:=1 to m do
24   if c[i]=0 then exit(false);
25  exit(true);
26 end;
27 
28 begin
29  //assign(input,'cf732D.in'); reset(input);
30  //assign(output,'cf732D.out'); rewrite(output);
31  readln(n,m);
32  for i:=1 to n do read(a[i]);
33  for i:=1 to m do read(d[i]);
34  l:=1; r:=n; last:=n+1;
35  while l<=r do
36  begin
37   mid:=(l+r)>>1;
38   if isok(mid) then begin last:=mid; r:=mid-1; end
39    else l:=mid+1;
40  end;
41  if last=n+1 then writeln(-1)
42   else writeln(last);
43  //close(input);
44  //close(output);
45 end.