关键字:堆。
Link&Limit
时间限制:1000ms 空间限制:131072kb
Description
有n个函数,分别为F1,F2,...,Fn。定义Fi(x)=Ai*x^2+Bi*x+Ci (x∈N*)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复的要输出多个)。
Input Format
第一行输入两个正整数n和m。以下n行每行三个正整数,其中第i行的三个数分别位Ai、Bi和Ci。Ai<=10,Bi<=100,Ci<=10 000。
Output Format
输出将这n个函数所有可以生成的函数值排序后的前m个元素。这m个数应该输出到一行,用空格隔开。
Sample Input #1
3 10
4 5 3
3 4 5
1 7 1
Sample Output #1
9 12 12 19 25 29 31 44 45 54
Hint
对于100%的数据,n,m<=10000。
堆的基础题,与洛谷P1631类似。由于Ai,Bi,Ci>0,所以每一个函数在定义域内都是增函数。那么,我们将F1(1),F2(1)...Fn(1)全部加入小根堆,每次取出堆顶元素Fx(y),输出并将Fx(y+1)加入堆中,重复进行m次即可。
#include <cstdio> struct node { int id,now,sum; node operator = (node x) { id = x.id; now = x.now; sum = x.sum; return *this; } }; struct heap { node h[30010]; int tot; heap() { tot = 0;} void add(node x) { int i = ++tot,j = i>>1; h[tot] = x; for(;i>1;i=j,j>>=1) { if(x.sum<h[j].sum) {h[i] = h[j]; h[j] = x;} else break; } } void del() { int i = 1,j = 2; node x = h[1] = h[tot--]; for(;j<=tot;i=j,j<<=1) { if(j<tot) if(h[j+1].sum<h[j].sum) j++; if(x.sum>h[j].sum) {h[i] = h[j]; h[j] = x;} else break; } } }heaps; int n,m,a[10010],b[10010],c[10010]; int main() { int i; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d%d%d",&a[i],&b[i],&c[i]); node x; x.id = i; x.now = 1; x.sum = a[i]+b[i]+c[i]; heaps.add(x); } for(i=1;i<=m;i++) { printf("%d ",heaps.h[1].sum); node x = heaps.h[1]; x.now++; x.sum = a[x.id]*x.now*x.now+b[x.id]*x.now+c[x.id]; heaps.add(x); heaps.del(); } return 0; }