wikioi 1245最小的N个和

2013-09-08 10:12

LRJ的算法竞赛入门经典训练指南里有类似的题,原题要难很多,p189页

读入A,B两组中的所有数后,建立N个有序表:

A1+B1<A2+B1<A3+B1<...<AN+B1

A1+B2<A2+B2<A3+B2<...<AN+B2

...

A1+BN<A2+BN<A3+BN<...<AN+AN

将每个有序表的第一个数字(记作s)连同A,B的下标0推入优先队列,这样我们每一次取出队列中的队首,显然这个元素的s是最小的,输出。与此同时,我们需要延续这个有序表。在取出的结构体中,令其标号a加1,b的标号不变,那么,s=B[b]+A[a]。

实际操作时,因为b的标号不变,就可以不保存下标b以及数组B,直接将读入数组B改为读入每一个元素(记为k),并将s=k+a[1],a=1推入队列,每次取出元素后,令其a=a+1,s=s+A[a]-A[a-1],如此减少空间占用,只需要一个队列和一个保存A的数组

//By BLADEVIL

type

    aa=record

    num                 :array[0..100010] of longint;

end;

    bb=record

    num,size            :longint;

 

end;

 

var

    x, y                :aa;

    n                   :longint;

    heap                :array[0..300010] of bb;

    t                   :longint;

 

 

procedure swap(var a,b:longint);

var

    z                   :longint;

begin

    z:=a; a:=b; b:=z;

end;

 

procedure qs(var xx:aa; low,high:longint);

var

    i, j, z,  c         :longint;

begin

    i:=low; j:=high; c:=xx.num[(i+j) div 2];

    while i<j do

    begin

        while c<xx.num[j] do dec(j);

        while c>xx.num[i] do inc(i);

        if i<=j then

        begin

            swap(xx.num[i],xx.num[j]);

            inc(i); dec(j);

        end;

    end;

    if i<high then qs(xx,i,high);

    if j>low then qs(xx,low,j);

end;

 

procedure init;

var

    i                   :longint;

begin

    read(n);

    for i:=1 to n do read(x.num[i]);

    for i:=1 to n do read(y.num[i]);

    qs(x,1,n);

    qs(y,1,n);

end;

 

procedure up(x:longint);

begin

    while (x>1) and (heap[x].num<heap[x div 2].num) do

    begin

        swap(heap[x].num,heap[x div 2].num);

        swap(heap[x].size,heap[x div 2].size);

        x:=x div 2;

    end;

end;

 

procedure down(x:longint);

var

    k                   :longint;

begin

    k:=x;

    while true do

    begin

        if (x<<1<=t) and (heap[k].num>heap[x<<1].num) then k:=x<<1;

        if (x<<1+1<=t) and (heap[k].num>heap[x<<1+1].num) then k:=x<<1+1;

        if k=x then exit;

        swap(heap[x].num,heap[k].num);

        swap(heap[x].size,heap[k].size);

        x:=k;

    end;

end;

 

procedure main;

var

    i                   :longint;

begin

    t:=0;

    for i:=1 to n do

    begin

        inc(t);

        heap[t].num:=x.num[i]+y.num[1];

        heap[t].size:=1;

        up(t);

    end;

    for i:=1 to n do

    begin

        write(heap[1].num,' ');

        inc(t);

        heap[t].num:=heap[1].num-y.num[heap[1].size]+y.num[heap[1].size+1];

        heap[t].size:=heap[1].size+1;

        up(t);

        heap[1].num:=heap[t].num;

        heap[1].size:=heap[t].size;

        dec(t);

        down(1);

 

    end;

    writeln;

end;

 

begin

    init;

    main;

end.

 

你可能感兴趣的:(IO)