1150: [CTSC2007]数据备份Backup
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 758 Solved: 317
[ Submit][ Status]
Description
Input
输入的第一行包含整数n和k,其中n(2 ≤ n ≤100 000)表示办公楼的数目,k(1≤ k≤ n/2)表示可利用的网络电缆的数目。接下来的n行每行仅包含一个整数(0≤ s ≤1000 000 000), 表示每个办公楼到大街起点处的距离。这些整数将按照从小到大的顺序依次出现。
Output
输出应由一个正整数组成,给出将2K个相异的办公楼连成k对所需的网络电缆的最小总长度。
Sample Input
5 2
1
3
4
6
12
1
3
4
6
12
Sample Output
4
HINT
上面的样例输入给出了前面描述的示例情形 对于每一个测试点,如果写到输出文件中的答案正确,则得到该测试点100%的分数,否则得零分。30%的输入数据满足n≤20。60%的输入数据满足n≤10 000。
题解:
首先要推出相邻的是最短的,但是相邻有种情况如样例:当你选取四个点中间两个点时,这两个点的距离加上两边的点之间的距离大于左边两点之间的距离与右边两点的距离,所以处理问题在用堆取出最小值(中间两点)要将左边两点和右边两点的距离和加入堆中,为了更好的表示取左边两个和右边两点时的情况,加入的是距离和减去中间两点的距离,这样加入后就将加入中间两点的距离消去。
代码:
program pro;
type heap=record pr,po:longint; end;
var
he:array[-1..100]of heap;
pos,ne,pre:array[-1..100050]of longint;
lo:array[0..100050]of longint;
ans,tot,n,m:longint;
procedure swap(var x,y:longint);
var
k:longint;
begin
k:=x; x:=y; y:=k;
end;
procedure pushup(x:longint);
begin
while (he[x].pr<he[x shr 1].pr) do
begin
pos[he[x shr 1].po]:=x;
swap(he[x].pr,he[x shr 1].pr);
swap(he[x].po,he[x shr 1].po);
x:=x shr 1;
end;
pos[he[x].po]:=x;
end;
procedure pushdown(x:longint);
var
tmp:longint;
begin
while (x shl 1<=tot) do
begin
tmp:=x shl 1;
if (tmp<tot)and(he[tmp].pr>he[tmp+1].pr) then inc(tmp);
if (he[x].pr>he[tmp].pr) then
begin
pos[he[tmp].po]:=x;
swap(he[x].pr,he[tmp].pr);
swap(he[x].po,he[tmp].po);
x:=tmp;
end
else break;
end;
pos[he[x].po]:=x;
end;
procedure push(x,y:longint);
begin
inc(tot);
he[tot].pr:=x; he[tot].po:=y; pos[y]:=tot;
pushup(tot);
end;
procedure delete(x:longint);
begin
he[x].pr:=maxlongint;
pushdown(x);
end;
procedure init;
var
i:longint;
begin
readln(n,m);
for i:=1 to n do readln(lo[i]);
for i:=2 to n do
begin
pre[i]:=i-1; ne[i]:=i+1;
push(lo[i]-lo[i-1],i);
end;
pre[2]:=-1; ne[n]:=-1;
end;
procedure main;
var
i,j,a,b:longint;
k:heap;
begin
init;
for i:=1 to m do
begin
k.pr:=he[1].pr; k.po:=he[1].po;
if pre[k.po]=-1 then
begin
inc(ans,k.pr);
delete(1); delete(pos[ne[k.po]]);
pre[ne[ne[k.po]]]:=-1;
end
else
if ne[k.po]=-1 then
begin
inc(ans,k.pr);
delete(1); delete(pos[pre[k.po]]);
ne[pre[pre[k.po]]]:=-1;
end
else
begin
inc(ans,k.pr);
a:=ne[k.po]; b:=pre[k.po];
pre[k.po]:=pre[b]; ne[pre[b]]:=k.po;
ne[k.po]:=ne[a]; pre[ne[a]]:=k.po;
he[1].pr:=he[pos[a]].pr+he[pos[b]].pr-he[1].pr;
pushdown(1);
delete(pos[a]); delete(pos[b]);
end;
end;
writeln(ans);
end;
begin
main;
end.