第一层思路:暴力o(n^2),超时;
第二层思路:高度从大到小排序,所有数加入堆,利用sum求出以h[i]为最高高度的所有大于h[i]的c[i]之和(很绕),每次做完后sum加上所有当前=h[i]的c[i]之和。大根堆维护最大值,连取d[i]-1(h[i]有几个)个,再用g(堆里所有数之和)-g1(被取的最大值之和)求出f[i]为最高高度下面的最优解。sum+g-g1为上下最优解之和。每次做完后,将h[i],c[i]退堆。答案为min(sum+g-g1)。时间复杂度O(n log n),可过,但有些复杂。。。。
第三层思路(先看懂第二层):高度从小到大排序!这样加入堆的都有用,复杂(猥琐)的退堆省略;仍是大根堆维护最大值,g-g1方法没变。以h[i]为最高高度上面的c[i]之和用sum储存,sum初值为c[i]之和。每次sum减以h[i]为高度的c[i]之和,答案同上。时间复杂度o(n log n),可过,较为简单!
思路较为简单,考实现能力!
程序框架:
1,定义变量;
2,快排(5)后;
3,up操作;
4,down操作;
5,读入;
6,快排后求需要的值(如sum等);
7,o(n)枚举循环;
8,sum减;
9,ans=sum;
10,求出h[i]下面的最优解;
11,ans:=ans+下面最优解;
12,取ans的min
13,输出min
希望对大家有帮助!
var
i,j,k,m,n,o,p,l,s,t,sum,len,ans,min,g,g1:longint;
a,b,c,d,x,y,a1,b1,c1,max1,max2:array[0..100000] of longint;
bz:array[1..100000] of boolean;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
i:=l;
j:=r;
mid:=x[(l+r) div 2];
repeat
while x[i]<mid do inc(i);
while x[j]>mid do dec(j);
if i<=j then begin
k:=x[i];x[i]:=x[j];x[j]:=k;
k:=y[i];y[i]:=y[j];y[j]:=k;
inc(i);dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure up(x:longint);
begin
while (x>1) and (a[x]>a[x div 2]) do begin
t:=a[x];a[x]:=a[x div 2];a[x div 2]:=t;
t:=b[x];b[x]:=b[x div 2];b[x div 2]:=t;
x:=x div 2;
end;
end;
procedure down(x:longint);
var
xx:longint;
begin
while ((x*2<=len) and (a[x*2]>a[x])) or ((x*2+1<=len) and (a[x*2+1]>a[x])) do begin
xx:=x*2;
if (xx+1<=len) and (a[xx+1]>a[xx]) then inc(xx);
t:=a[x];a[x]:=a[xx];a[xx]:=t;
t:=b[x];b[x]:=b[xx];b[xx]:=t;
x:=xx;
end;
end;
function small(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
assign(input,'house.in');reset(input);
assign(output,'house.out');rewrite(output);
readln(n);
for i:=1 to n do readln(x[i],y[i]);
qsort(1,n);
for i:=1 to n do begin
inc(c[x[i]],y[i]);
inc(d[x[i]]);
inc(sum,y[i]);
end;
for i:=1 to n do
if d[x[i]]>n-d[x[i]] then begin
writeln(0);
close(input);close(output);
halt;
end;
fillchar(bz,sizeof(bz),true);
min:=maxlongint;
for i:=1 to n do begin
if bz[x[i]]=false then begin
inc(len);a[len]:=y[i];b[len]:=x[i];inc(g,y[i]);up(len);
continue;
end;
bz[x[i]]:=false;
max1[0]:=0;
max2[0]:=0;
dec(sum,c[x[i]]);
ans:=sum;
g1:=0;
p:=0;
for j:=1 to small(len,d[x[i]]-1) do begin
inc(g1,a[1]);
if a[1]<a[len] then p:=1 else p:=0;
inc(max1[0]);max1[max1[0]]:=a[1];
inc(max2[0]);max2[max2[0]]:=b[1];
a[1]:=a[len];
b[1]:=b[len];
begin
down(1);
dec(len);
end;
end;
inc(ans,g-g1);
if ans<min then min:=ans;
for j:=1 to max1[0] do begin
inc(len);a[len]:=max1[j];b[len]:=max2[j];up(len);
end;
inc(len);a[len]:=y[i];b[len]:=x[i];inc(g,y[i]);up(len);
end;
writeln(min);
close(input);close(output);
end.