noip2012 借教室

描述

在大学期间,经常需要租借教室。大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室。教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样。

面对海量租借教室的信息,我们自然希望编程解决这个问题。我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借。共有m份订单,每份订单用三个正整数描述,分别为dj,sj,tj,表示某租借者需要从第sj天到第tj天租借教室(包括第sj天和第tj天),每天需要租借dj个教室。 
我们假定,租借者对教室的大小、地点没有要求。即对于每份订单,我们只需要每天提供dj个教室,而它们具体是哪些教室,每天是否是相同的教室则不用考虑。

借教室的原则是先到先得,也就是说我们要按照订单的先后顺序依次为每份订单分配教室(这句话很重要,这决定了分配是按照顺序的)。如果在分配的过程中遇到一份订单无法完全满足,则需要停止教室的分配,通知当前申请人修改订单。这里的无法满足指从第sj天到第tj天中有至少一天剩余的教室数量不足dj个。

现在我们需要知道,是否会有订单无法完全满足。如果有,需要通知哪一个申请人修改订单。


program classroom;
var n,m,i,s1,l,r,mid,now:longint;
    r1,sum:array[1..1000000]of longint;
    d,s,t:array[1..1000000]of longint;
    flag:boolean;
begin
 read(n,m);
 for i:=1 to n do read(r1[i]);
 for i:=1 to m do
  read(d[i],s[i],t[i]);
 l:=1;r:=m+1; //二分终点要注意,如果最后终点不变,直到m+1才不合格,那么借用要求全部满足;如果r改变了,那么要求不满足
 now:=0;//如果可行一定是连续的订单,所以可用二分 now指的是上一个mid,为了恢复sum数组
 repeat
  mid:=(l+r) shr 1;
  if mid>now then
   begin
    for i:=now+1 to mid do
     begin
      inc(sum[s[i]],d[i]);
      dec(sum[t[i]+1],d[i]);  //用到差分
     end;
   end
  else
   begin
    for i:=mid+1 to now do
     begin
      dec(sum[s[i]],d[i]);
      inc(sum[t[i]+1],d[i]);
     end;
   end;
  now:=mid;
  flag:=true;
  s1:=0;
  for i:=1 to n do //sum[]按照天数计
   begin
    s1:=s1+sum[i];
    if s1>r1[i] then begin flag:=false;break;end;
   end;
  if flag then
   l:=mid+1
  else
   r:=mid;
 until l=r;  //表示不满足的位置,所以初始r=m+1
 if (flag)and(l=m+1) then
  write(0)
 else
  begin
   writeln(-1);
   write(r);
  end;
end.


你可能感兴趣的:(二分)