第三部分 數據結構 -- 第三章 樹-1370:最小函數值(minval)

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章