洛谷题单指南-二叉堆与树状数组-P2085 最小函数值

原题链接:https://www.luogu.com.cn/problem/P2085

题意解读:有n个函数,函数中x取值>=1,计算所有函数能得到的值中最小的m个。

解题思路:

函数中x取值是>=1的整数,因此每个函数的值是f(1),f(2),f(3)....,是一个递增序列,题目本质上是要从n个递增序列中找到前m个最小的数。

首先,对所有函数计算f(1),放入优先队列,最小值一定在其中。

第二小的值如何计算?可以将最小的f(1)弹出,计算相应的f(2),再放回优先队列,再取此时最小值,即可得到第二小的值。

第三、四。。。m小的值计算方法以此类推。

用算法的语言描述:

1、初始计算所有函数在x=1时的值

2、取最小值

3、然后将最小值对应的函数x+1再计算函数值

4、重复2,直到取m次最小值

由于优先队列要记录函数值,取得函数值时x的值,以及第几个函数,因此可以定义结构体

struct Node
{
    int val, idx, x; //val函数值,idx函数编号,x未知数取值
    bool operator < (const Node &node) const &
    {
        if(val != node.val) return val > node.val;
        if(x != node.x) return x > node.x;
        return idx > node.idx;
    }
};

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 10005;

struct Node
{
    int val, idx, x; //val函数值,idx函数编号,x未知数取值
    bool operator < (const Node &node) const &
    {
        if(val != node.val) return val > node.val;
        if(x != node.x) return x > node.x;
        return idx > node.idx;
    }
};

int n, m;
int a[N], b[N], c[N];
priority_queue<Node> q;

int f(int idx, int x)
{
    return a[idx] * x * x + b[idx] * x + c[idx];
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++) 
    {
        cin >> a[i] >> b[i] >> c[i];
        q.push({f(i, 1), i, 1});
    }
    while(m--)
    {
        Node p = q.top(); q.pop();
        cout << p.val << " ";
        q.push({f(p.idx, p.x + 1), p.idx, p.x + 1});
    }
    return 0;
}

 

posted @ 2024-11-11 15:55  五月江城  阅读(9)  评论(0编辑  收藏  举报