Codeforces Round #390 (Div. 2) D. Fedor and coupons

原题网址:http://codeforces.com/contest/754/problem/D

这里写图片描述
这里写图片描述
大意是n个区间选k个,使得所有区间交集最大。
显然区间交的开始点肯定为一个左端点,按照左端点排序,维护两个堆,堆里记区间右端点,一开始先塞到大根堆里,若小根堆不满k个,就把大根堆里的压到小根堆里去。当小根堆满k个就可以统计答案。途中注意删除过期的点。

换元素换位置写错了,还有标号标错了,比赛时WA光(像这种标号的问题一定要特别当心啊啊啊)。
Pascal写得很长。。。不过cf码6KB还调出样例还是头一次

type
  rec1=record
         x,num:longint;
       end;
  rec2=record
         k,p:longint;
       end;
const
  MAXN=300050;
var
  heap:array[0..1,0..MAXN] of rec1;
  co:array[0..MAXN] of rec2;
  a,b,c,num,note:array[0..MAXN] of longint;
  s:array[0..1] of longint;
  n,k,i,p,q,ans,now:longint;
function max(a,b:longint):longint;
  begin if(a>b) then exit(a) else exit(b); end;
procedure swap(var a,b:longint);
  var t:longint;
  begin t:=a;a:=b;b:=t; end;
procedure swp(k,a,b:longint);
  begin
    swap(heap[k][a].x,heap[k][b].x);
    swap(heap[k][a].num,heap[k][b].num);
    swap(co[heap[k][a].num].p,co[heap[k][b].num].p);
  end;
procedure sort(l,r:longint);
  var
    i,j,e:longint;
  begin
    i:=l;j:=r;e:=a[(l+r)>>1];
    repeat
      while a[i]<e do inc(i);
      while e<a[j] do dec(j);
      if not (i>j) then
        begin
          swap(a[i],a[j]);
          swap(b[i],b[j]);
          swap(note[i],note[j]);
          inc(i);dec(j);
        end;
    until i>j;
    if l<j then sort(l,j);
    if i<r then sort(i,r);
  end;
procedure sort2(l,r:longint);
  var
    i,j,e:longint;
  begin
    i:=l;j:=r;e:=c[(l+r)>>1];
    repeat
      while c[i]<e do inc(i);
      while e<c[j] do dec(j);
      if not (i>j) then
        begin
          swap(c[i],c[j]);
          swap(num[i],num[j]);
          inc(i);dec(j);
        end;
    until i>j;
    if l<j then sort2(l,j);
    if i<r then sort2(i,r);
  end;
procedure heapup1(i:longint);
  begin
    while (i>1)and(heap[1][i].x<heap[1][i>>1].x) do
      begin
        swp(1,i,i>>1);
        i:=i>>1;
      end;
  end;
procedure heapup0(i:longint);
  begin
    while (i>1)and(heap[0][i].x>heap[0][i>>1].x) do
      begin
        swp(0,i,i>>1);
        i:=i>>1;
      end;
  end;
procedure heapdown1(i:longint);
  var
    e:longint;
  begin
    while (i<<1<=s[1])and(heap[1][i<<1].x<heap[1][i].x)or(i<<1+1<=s[1])and(heap[1][i<<1+1].x<heap[1][i].x) do
      begin
        if (i<<1+1<=s[1])and(heap[1][i<<1+1].x<heap[1][i<<1].x)
          then e:=i<<1+1
          else e:=i<<1;
        swp(1,i,e);
        i:=e;
      end;
  end;
procedure heapdown0(i:longint);
  var
    e:longint;
  begin
    while (i<<1<=s[0])and(heap[0][i<<1].x>heap[0][i].x)or(i<<1+1<=s[0])and(heap[0][i<<1+1].x>heap[0][i].x) do
      begin
        if (i<<1+1<=s[0])and(heap[0][i<<1+1].x>heap[0][i<<1].x)
          then e:=i<<1+1
          else e:=i<<1;
        swp(0,i,e);
        i:=e;
      end;
  end;
procedure push(k,x,num:longint);
  begin
    inc(s[k]);
    heap[k][s[k]].x:=x;
    heap[k][s[k]].num:=num;
    co[num].k:=k;
    co[num].p:=s[k];
    if (k=1)
      then heapup1(s[k])
      else heapup0(s[k]);
  end;
procedure poop(k:longint);
  begin
    heap[k][1]:=heap[k][s[k]];
    co[heap[k][1].num].p:=1;
    dec(s[k]);
    if (k=1)
      then heapdown1(1)
      else heapdown0(1);
  end;
procedure move(k,i:longint);
  var
    t:longint;
  begin
    heap[k][i]:=heap[k][s[k]];
    co[heap[k][i].num].p:=i;
    dec(s[k]);
    t:=heap[k][i].num;
    if (k=1)
      then
        begin
          heapup1(co[t].p);
          heapdown1(co[t].p);
        end
      else
        begin
          heapup0(co[t].p);
          heapdown0(co[t].p);
        end;
  end;
begin
  readln(n,k);
  for i:=1 to n do read(a[i],b[i]);
  for i:=1 to n do note[i]:=i;
  for i:=1 to n do c[i]:=b[i];
  for i:=1 to n do num[i]:=i;
  sort(1,n);
  sort2(1,n);
  p:=1;q:=1;ans:=0;s[0]:=0;s[1]:=0;
  while (p<=n) do
    begin
      now:=a[p];
      while (q<=n)and(c[q]<now) do
        begin
          move(co[num[q]].k,co[num[q]].p);
          inc(q);
        end;
      while (s[0]>0)and(s[1]<k) do
        begin
          push(1,heap[0][1].x,heap[0][1].num);
          poop(0);
        end;
      while (p<=n)and(a[p]=now) do
        begin
          if (s[1]<k)
            then push(1,b[p],note[p])
            else if (b[p]<=heap[1][1].x)
                   then push(0,b[p],note[p])
                   else
                     begin
                       push(0,heap[1][1].x,heap[1][1].num);
                       poop(1);
                       push(1,b[p],note[p]);
                     end;
          inc(p);
        end;
      if (s[1]=k)
       then ans:=max(ans,heap[1][1].x-now+1);
    end;
  p:=1;q:=1;s[0]:=0;s[1]:=0;
  while (p<=n) do
    begin
      now:=a[p];
      while (q<=n)and(c[q]<now) do
        begin
          move(co[num[q]].k,co[num[q]].p);
          inc(q);
        end;
      while (s[0]>0)and(s[1]<k) do
        begin
          push(1,heap[0][1].x,heap[0][1].num);
          poop(0);
        end;
      while (p<=n)and(a[p]=now) do
        begin
          if (s[1]<k)
            then push(1,b[p],note[p])
            else if (b[p]<=heap[1][1].x)
                   then push(0,b[p],note[p])
                   else
                     begin
                       push(0,heap[1][1].x,heap[1][1].num);
                       poop(1);
                       push(1,b[p],note[p]);
                     end;
          inc(p);
        end;
      if (s[1]=k)and(ans=heap[1][1].x-now+1) then
        begin
          writeln(ans);
          for i:=1 to k do
            a[i]:=heap[1][i].num;
          sort(1,k);
          for i:=1 to k-1 do
            write(a[i],' ');
          writeln(a[k]);
          halt;
        end;
    end;
  writeln(0);
  for i:=1 to k-1 do
    write(i,' ');
  writeln(k);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值