1370:最小函数值(minval)
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 3422 通过数: 1477
【题目描述】
有n个函数,分别为F1,F2,…,Fn。定义Fi(x)=Aix2+Bix+Ci(x∈N∗)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复的要输出多个)。
【输入】
第一行输入两个正整数n和m。
以下n行每行三个正整数,其中第i行的三个数分别位Ai、Bi和Ci。输入数据保证Ai≤10,Bi≤100,Ci≤10000。
【输出】
将这n个函数所有可以生成的函数值排序后的前m个元素。这m个数应该输出到一行,用空格隔开。
【输入样例】
3 10
4 5 3
3 4 5
1 7 1
【输出样例】
9 12 12 19 25 29 31 44 45 54
【提示】
【数据规模】
n,m≤10000。
思路:Max-heap: 父节点的值大于或等于子节点的值;父节点的值大于或等于子节点的值,如下例子:
建一个大根堆,存最小的数到第m小的数,第m小的数就是堆顶,每次只需要比较新加进来的数比堆顶大还是比堆顶小,如果比堆顶小,将原来的堆顶丢掉,将新的数压入;题意,a>0 && b>0,函数对称轴x = −b / 2 ∗ a<0,==> y在x > 0时是单调递增,函数值y只会大不会小,可以直接break掉了。大根堆,要逆序输出,将m个数从小到大输出。
#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;
int ans[10010];
priority_queue<int,vetcor<int>,less<int> > q;
int main(){
int n,m;
cin >> n>> m;
for(int i = 1; i <= n; i++){
int a,b,c;
cin >> a >> b >> c;
for(int j = 1; j <= m; j++)
{
int k = a*j*j + b*j + c;
if(i == 1) q.push(k);
else
{
if(k < q.top()){//如果比堆顶小,将原来的堆顶丢掉,将新的数压入
q.push(k);
q.pop();
}
else break;
}
}
}
for(int i = 1; i <= m; i++){
ans[i] = q.top();
q.pop();
}
for(int i = m ; i >= 1; i--)//大根堆,要逆序输出
{
cout << ans[i] <<" ";
}
return 0;
}