原來對堆雖然理論比較瞭解但只打過幾個堆排序,最近複習一下吧。
POJ3253
{FJ要把一條木棒切成給定長度的n根木條,每次的花費是木棒的長度,求總花費和合并果子基本一樣,但是題目描述是逆向的,需要一點思考,可以把切割看成合并,貪心得合并最小的木條並記錄最花費雖然用隊列是最優的,但就用來練習基本的heap操作吧,支援下濾,返回並刪除最小元2011-06-19 22:41}var a:array[0..1000000] of longint; heapsize:longint; m,n,min1,min2:longint; i,j,k:longint; ans:int64;procedure heap_down(k:longint);var i,x:longint;begin x:=a[k]; i:=k*2; while i<=heapsize do begin if (i<heapsize)and(a[i]>a[i+1]) then inc(i); if a[i]<x then begin a[k]:=a[i]; k:=i; i:=i*2; end else break; end; a[k]:=x;end;procedure swap(var a,b:longint);var c:longint;begin c:=a; a:=b; b:=c;end;function get_min:longint;var x:longint;begin swap(a[1],a[heapsize]); dec(heapsize); heap_down(1); exit(a[heapsize+1]);end;procedure insert(key:longint);var i:longint;begin inc(heapsize); i:=heapsize; while a[i div 2]>key do begin a[i]:=a[i div 2]; i:=i div 2; end; a[i]:=key;end;begin readln(n); for i:=1 to n do read(a[i]); heapsize:=n; for i:=heapsize div 2 downto 1 do heap_down(i); for i:=1 to n-1 do begin min1:=get_min; min2:=get_min; inc(ans,min1+min2); insert(min1+min2); end; writeln(ans);end.
POJ2051(WA的代碼)
{題意:輸入N個任務編號和延時,每次執行任務後任務的延時會增加開始時的延時,按順序輸出前M個任務執行的編號(延時一樣時按編號順序)。建一個小根堆。每次輸出堆頂元素並增加堆頂元素關鍵字的值並下濾即可不知為什麼WA2011-06-19 22:15}type data=record delay,time,num:longint end;var a:array[0..100000] of data; i,j,k,m,n:longint; s:string[7]; c:char;procedure heap_down(k:longint);var x:data; i:longint;begin x:=a[k]; i:=k*2; while i<=n do begin if (i<n) and ( (a[i].delay>a[i+1].delay) or ( (a[i].delay=a[i+1].delay) and (a[i].num>a[i+1].num) ) ) then inc(i); if x.delay>a[i].delay then begin a[k]:=a[i]; k:=i; i:=i*2; end else break; end; a[k]:=x;end;procedure inc_key(k,add:longint);begin inc(a[k].delay,add); heap_down(1);end;begin while not eof do begin n:=0; fillchar(a,sizeof(a),0); read(c); while c='R' do begin read(c,c,c,c,c,c,c); inc(n); readln(a[n].num,a[n].time); a[n].delay:=a[n].time; read(c); end; readln(m); for i:=n div 2 downto 1 do heap_down(i); for i:=1 to m do begin writeln(a[1].num); inc_key(1,a[1].time); end; end;end.