【每日一题】洛谷 P2085 (优先队列)

想她一次就背十个单词,当我英语过六级后,我就去告诉她,我很在意她
一天一道数论题,当我可以秒杀数论题的时候,就开始做 DP


今日份快乐:洛谷 P2085 传送门
明天份快乐:codeforces 1355C 传送门


题目大意

有 n 个二次函数,给出每个函数的系数 a、b 和 c,当 x > 0 时,请求出所有函数的所有函数值中最小的 m 个。
数据范围:
在这里插入图片描述

分析

题目的数据范围降低了题目难度,a、b、c 和 x 都为正整数,说明给出的 n 个函数都在 1 到正无穷大上单调递增。对于每一个函数,我们可以定义一个指针,让它指向 x = 1,这个时候的 y 值就是当前函数的最小值,我们把所有函数的最小值进行排序。每次取出所有函数的最小值中的最小值,并让这个函数的指针右移,右移以后再次排序,…………无限循环直到找到 m 个最小值
我们需要一直维护所有函数的最小值,这个时候需要用到优先队列

稍微讲一下优先队列
优先队列具有队列的所有特性,包括基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的
默认为升序,队列中的所有数据的最小值在队首
priority_queue< int >qu 就是一个储存 int 类型的优先队列

  • qu.top(); 可以返回队列的第一个元素,也就是所有元素的最小值
  • qu.pop(): 可以删除队列的第一个元素
  • qu.push(x);在队列中添加元素 x

这是本题要用到的三个函数,细节看代码

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;

typedef struct Node{   // 定义一个数据类型,具有二次函数的系数、自变量和函数值
	int a;
	int b;
	int c;
	int x;            // 分析中提到的指针
	int y;			  // 指针对应的函数值
} node;

bool operator < (const node &A, const node &B){    // 重载 < 号,让优先队列按照 y 的值进行排序
  	return A.y > B.y;
}

int f(node z, int x){  // 计算 x 对应的函数值
	return z.a * x * x + z.b * x + z.c;
}
int main(){
	
	ios::sync_with_stdio(false);
	
	int n, m;
	cin >> n >> m;
	node v;
	priority_queue<node>qu;     // 优先队列
	for(int i = 1; i <= n; i++){
		cin >> v.a >> v.b >> v.c;
		v.x = 1;			   // 默认 x = 1
		v.y = v.a + v.b +  v.c;;
		qu.push(v);  		   // 把这个二次函数加到队列中
	} 
		
	vector<int>res;            // 放答案
	int ans = 0;			   // 答案个数
	while(ans <= m){           
		node now = qu.top();   // 取出队首元素
		qu.pop();			   // 因为要更新这个函数,把原来的函数删去
		res.push_back(now.y);  // 记录答案
		ans++;				   // 更新答案个数
		now.x++;               // 指针右移
		now.y = f(now, now.x); // 更新函数
		qu.push(now);		   // 更新队列,重新排序
	}
	
	for(int i = 0; i < m; i++) cout << res[i] << " ";
	
	return 0;
}

坚持的时候很狼狈,等成功以后,丑的还是丑的🤭

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值