8.2 minval

来源:互联网 发布:中国行政区划矢量数据 编辑:程序博客网 时间:2024/06/16 01:06

4.【最小函数值】minval

【题目描述】
    有n个函数,分别为F1,F2,...,Fn。定义Fi(x)=Ai*x^2+Bi*x+Ci(x∈N*)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复的要输出多个)。

【输入格式】
    第一行输入两个正整数n和m。
    以下n行每行三个正整数,其中第i行的三个数分别为Ai、Bi和Ci。输入数据保证Ai<=10,Bi<=100,Ci<=10 000。

【输出格式】
    输出将这n个函数所有可以生成的函数值排序后的前m个元素。
    这m个数应该输出到一行,用空格隔开,并且最后一个数右侧也有一个空格。

【样例输入】
3 10
4 5 3
3 4 5
1 7 1

【样例输出】
9 12 12 19 25 29 31 44 45 54

【数据范围】

50%的数据:n,m<=1000
100%的数据:n,m<=500 000

思路:其实很简单,因为a,b,c>0,x>0 所以函数单调递增,把每个函数从x=1开始枚举再排序就行了

程序:

type
  tree=record
   x,y:longint;
   a,b,c:integer;
end;
var
  f:array[0..500000]of tree;
  n,m,i,j,k:longint;
procedure build(c:longint);
var
  i,p:longint;
  t:tree;
begin
  p:=c>>1;
  t:=f[c];
  while (p>0)and(t.y<f[p].y) do
   begin
     f[c]:=f[p];
     c:=p;
     p:=c>>1;
   end;
  f[c]:=t;
end;
procedure init;
begin
  readln(n,m);
  for i:=1 to n do
   begin
     readln(f[i].a,f[i].b,f[i].c);
     f[i].x:=1;
     f[i].y:=f[i].a+f[i].b+f[i].c;
     build(i);
   end;
end;
procedure hp;
var
  t:tree;
  i,j,p,c:longint;
begin
  t:=f[1];
  p:=1;
  c:=p<<1;
  if c>n then exit;
  while c<=n do
   begin
     if f[c+1].y<f[c].y then c:=c+1; if c>n then break;
     if t.y>f[c].y then f[p]:=f[c] else break;
     p:=c;
     c:=p<<1;
   end;
  f[p]:=t;
end;
procedure doit;
var
  i,j:longint;
begin
  for i:=1 to m do
   begin
     write(f[1].y,' ');
     inc(f[1].x);
     f[1].y:=f[1].x*f[1].x*f[1].a+f[1].x*f[1].b+f[1].c;
     hp;
   end;
end;
begin
  assign(input,'minval.in');
  assign(output,'minval.out');
  reset(input);
  rewrite(output);
  init;
  doit;
  close(input);
  close(output);
end.

反思:我当时用插排得了90分,oye~

      标准做法真的和堆排很像。。。