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;
}