每日一题010-堆-洛谷p2085最小函数值

P2085 最小函数值

题目描述

n n n 个函数,分别为 F 1 , F 2 , … , F n F_1,F_2,\dots,F_n F1,F2,,Fn。定义 F i ( x ) = A i x 2 + B i x + C i ( x ∈ N ∗ ) F_i(x)=A_ix^2+B_ix+C_i(x\in\mathbb N*) Fi(x)=Aix2+Bix+Ci(xN)。给定这些 A i A_i Ai B i B_i Bi C i C_i Ci,请求出所有函数的所有函数值中最小的 m m m 个(如有重复的要输出多个)。

输入格式

第一行输入两个正整数 n n n m m m

以下 n n n 行每行三个正整数,其中第 i i i 行的三个数分别为 A i A_i Ai B i B_i Bi C i C_i Ci

输出格式

输出将这 n n n 个函数所有可以生成的函数值排序后的前 m m m 个元素。这 m m m 个数应该输出到一行,用空格隔开。

输入输出样例 #1

输入 #1

3 10
4 5 3
3 4 5
1 7 1

输出 #1

9 12 12 19 25 29 31 44 45 54

说明/提示

数据规模与约定

对于全部的测试点,保证 1 ≤ n , m ≤ 10000 1 \leq n,m\le10000 1n,m10000 1 ≤ A i ≤ 10 , B i ≤ 100 , C i ≤ 1 0 4 1 \leq A_i\le10,B_i\le100,C_i\le10^4 1Ai10,Bi100,Ci104

思路

由于A,B都有数据限制,所以很显然这个二次函数的对称轴在x的负半轴,也就是说,我们研究的正半轴部分永远是递增的。省去了一个大麻烦,然后我维护一个小根堆,把每个函数的前m个值都放进去,最后输出小根堆的前m个值。

但是这样的话就需要n*m的空间,无法接受。

回想一下对顶堆,我们始终维护前m个值就行了。所以我们需要大根堆,如果比大根堆的最大值要大,那就不需要进入这个大根堆,具体看代码

代码

#include 
#include 
using i64 = long long;

int n, m;
int a,b,c;
int ans[10004];
std::priority_queue<int> qq;
int main()
{
	std::cin>>n>>m;
	std::cin>>a>>b>>c;
	for(int i = 1; i<=m; i++)
	{
		int v = a*i*i+b*i+c;
		qq.push(v);
	}
	for(int j = 2; j<=n; j++)
	{
		std::cin>>a>>b>>c;
		for(int i = 1; i<=m; i++)
		{
			int v = a*i*i+b*i+c;
			if(v<qq.top())
			{
				qq.push(v);
				qq.pop();
			}
			else{ break;}  //由于是递增的,一个不行,后面都不行
		}
	}
	for(int i = m; i>=1; i--)
	{
		ans[i] = qq.top();
		qq.pop();
	}
	for(int i = 1; i<=m; i++)
	{
		std::cout<<ans[i]<<' ';
	}
	return 0;
}

你可能感兴趣的:(每日一题,算法,java,开发语言,数据结构,蓝桥杯,c++)