【二叉堆】k路归并问题(BSOJ1941)

Description

  有n个函数,分别为F1,F2,…,Fn。定义Fi(x)=Ai*x^2+Bi*x+Ci(x∈N*)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复的要输出多个)。

Input

  第一行输入两个正整数n和m。以下n行每行三个正整数,其中第i行的三个数分别位Ai、Bi和Ci。Ai<=10,Bi<=100,Ci<=10 000。

Output

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

Sample Input

3 10
4 5 3
3 4 5
1 7 1

Sample Output

9 12 12 19 25 29 31 44 45 54

Hint

  n,m<=10,000


Thinking

  首先根据二次函数的知识可以判断出,这里的每个函数在x>0范围内都是单调递增的。

  可以根据堆的思想做这道题。开始时将每一个函数的第一个函数值加入小根堆,注意这里堆必须记录是第几个函数。每次取出堆顶元素加入到答案中,同时将堆顶元素所在的函数下标+1,将新得到的函数值加入堆中。重复以上步骤直到取出m个答案。

  时间复杂度O(mlogn)

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

struct func
{
    int a,b,c,x;
}data[10050];
struct node
{
    int data,k;
    friend bool operator >(const node &a,const node &b) {return a.data>b.data;}
    friend bool operator <(const node &a,const node &b) {return a.data<b.data;}
    //这两行用来自定义node类型的比较函数以便优先队列调用
}heap[10050];

int n,m;

int t[10050];

priority_queue<node,vector<node>,greater<node> > q;
int calc(int k)
{
    int temp=0;
    temp+=data[k].c;
    temp+=data[k].b*data[k].x;
    temp+=data[k].a*data[k].x*data[k].x;
    data[k].x++;
    return temp;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&data[i].a,&data[i].b,&data[i].c);
        data[i].x=1;
    }
    for(int i=1;i<=n;i++)
    {
        node temp;
        temp.data=calc(i);
        temp.k=i;
        q.push(temp);
    }
    for(int i=1;i<m;i++)
    {
        printf("%d ",q.top().data);
        int cc=q.top().k;
        node temp;
        temp.data=calc(cc);
        temp.k=cc;
        q.pop();
        q.push(temp);
    }
    printf("%d\n",q.top().data);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值