Sequence(pascal)堆

题意:

给n各组的数,每个组m个数,求出每个组去一个数的的和最小的m个数。

思路:

可以记录一个Δ为每个组的数对答案的影响,然后用堆维护Δ的最小值,然后会超时…..mdzz
这题想了我半天,本来想直接去网上看题解的,结果ymw大神说自己想(虽然他自己都想错了)。然后万般无奈就只能去百度搜索了。
正解:
1.将第一组数据输入arr1数组,升序排序。
2.将接下来的数据输入到arr2数组中,并且heap[i]=arr1[0]+arr2[0…n-1],
然后建一个堆
3.arr1数组从1到n-1,比较temp=arr1[i]+arr2[0…n-1]与堆顶的元素,如果temp比较小,则将堆顶元素pop,添加temp到heap;否则跳出循环。
4.将heap中的元素全部赋值给arr1数组,升序排序,重复2,3两步,直到所有数据全部处理完。

时间复杂度:

这题时间复杂度只看程序就是n次方logn。
但是在枚举每个数得时候最多就只会比较n次,然后就全部被break掉。所以就是(n*n*logn)

const
 maxn=2000;
 maxv=200;
var
 data,data1,dataq:array [0..maxn] of longint;
 f:array [0..maxn,0..maxv] of longint;
 sum,k,t,i,j,n,m,p,ii:longint;
 q:array [0..maxv] of longint;

procedure siftup(x:longint);
var
 i,j:longint;
begin
 i:=x;
 j:=x div 2;
 while j<>0 do
 begin
  if dataq[i]>dataq[j] then
  begin
   dataq[0]:=dataq[i];
   dataq[i]:=dataq[j];
   dataq[j]:=dataq[0];
  end else break;
  i:=j;
  j:=j div 2;
 end;
end;

procedure qsort(l,r:longint);
var
 i,j,mid:longint;
begin
 i:=l; j:=r;
 mid:=data[(l+r) div 2];
 while i<j do
 begin
  while data[i]<mid do inc(i);
  while data[j]>mid do dec(j);
  if i<=j then
  begin
   data[0]:=data[i];
   data[i]:=data[j];
   data[j]:=data[0];
   inc(i); dec(j);
  end;
 end;
 if i<r then qsort(i,r);
 if l<j then qsort(l,j);
end;

procedure siftdown(x:longint);
var
 i,j:longint;
begin
 i:=x;
 j:=x*2;
 while j<=m do
 begin
  if (j+1<=m) and (dataq[j]<dataq[j+1]) then inc(j);
  if dataq[j]>dataq[i] then
  begin
   dataq[0]:=dataq[i];
   dataq[i]:=dataq[j];
   dataq[j]:=dataq[0];
  end else break;
  i:=j;
  j:=j*2;
 end;
end;

begin
 readln(t);
 for k:=1 to t do
 begin
  fillchar(f,sizeof(f),$7f);
  sum:=0;
  readln(n,m);
  for i:=1 to m do
   read(data[i]);
  readln;
  for j:=1 to m-1 do
    for ii:=j+1 to m do
     if data[j]>data[ii] then
     begin
      data[0]:=data[j];
      data[j]:=data[ii];
      data[ii]:=data[0];
     end;
  for i:=1 to n-1 do
  begin
   for j:=1 to m do
    read(data1[j]);
   readln;

   for j:=1 to m-1 do
    for ii:=j+1 to m do
     if data1[j]>data1[ii] then
     begin
      data1[0]:=data1[j];
      data1[j]:=data1[ii];
      data1[ii]:=data1[0];
     end;

   for j:=1 to m do
   begin
    dataq[j]:=data[j]+data1[1];
    siftup(j);
   end;
   for j:=2 to m do
    for ii:=1 to m do
     if data1[j]+data[ii]<dataq[1] then
     begin
      dataq[1]:=data1[j]+data[ii];
      siftdown(1);
     end else break;
   data:=dataq;
   qsort(1,m);
   fillchar(dataq,sizeof(dataq),0);
  end;
  for i:=1 to m do
   write(data[i],' ');
  writeln;
 end;
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值