题目描述
有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个数应该输出到一行,用空格隔开。
输入输出样例
输入样例#1:
3 10
4 5 3
3 4 5
1 7 1
输出样例#1:
9 12 12 19 25 29 31 44 45 54
说明
数据规模:n,m<=10000
分析:
用一个优先队列q保存当前最小的m个函数值。
因为a,b,c>0,所以f(x)为增函数。所以这m个值一定在x=1,2,3…m中取得。
首先把第一个函数的前m个值压入队列中。对于第2、3、4……n个函数,每次将x遍历1到m。如果f(x)大于等于堆顶,那么x及x以后的函数值都比这m个大,可以不用计算了直接break掉。否则,弹出堆顶,将f(x)压入队列。
注意输出时倒序输出,用一个数组保存一下答案
代码:
type
see=record
t,pos,x:longint;
end;
const
maxn=10000;
var
a:array[1..maxn,1..3]of longint;
b:array[0..maxn]of see;
n,e,i,j:longint;
function fe(p,x:longint):longint;
begin
fe:=a[p,1]*x*x+a[p,2]*x+a[p,3];
end;
procedure down(m,k:longint);
var
tt:longint;
temp:see;
f:boolean;
begin
if k*2>m then exit;
f:=false;
repeat
k:=k*2;
if (k+1<=m)and(b[k+1].t<b[k].t) then k:=k+1;
if b[k].t<=b[k div 2].t then
begin
temp:=b[k div 2];
b[k div 2]:=b[k];
b[k]:=temp;
end
else f:=true;
until f or (k*2>m);
end;
begin
readln(n,e);
for i:=1 to n do
begin
readln(a[i,1],a[i,2],a[i,3]);
b[i].t:=fe(i,1);
b[i].pos:=i;
b[i].x:=1;
end;
for i:=n div 2 downto 1 do
down(n,i);
for i:=1 to e-1 do
begin
write(b[1].t,' ');
inc(b[1].x);
b[1].t:=fe(b[1].pos,b[1].x);
down(n,1);
end;
writeln(b[1].t);
end.