2017.08.15【NOIP 普及组】模拟赛C组 猴子拆房

第一层思路:暴力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 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 l1) 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 an-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]

 

 

你可能感兴趣的:(C组,堆,模拟,难题)