题目描述
有n个函数,分别为F1,F2,…,Fn。定义Fi(x)=Ai*x^2+Bi*x+Ci (x∈N*)。给定这些Ai、Bi和Ci,请求出所有函数的所有函数值中最小的m个(如有重复的要输出多个)。
输入输出格式
输入格式:
输入数据:第一行输入两个正整数n和m。以下n行每行三个正整数,其中第i行的三个数分别位Ai、Bi和Ci。Ai<=10,Bi<=100,Ci<=10 000。
输出格式:
输出数据:输出将这n个函数所有可以生成的函数值排序后的前m个元素。这m个数应该输出到一行,用空格隔开。
输入输出样例
输入样例#1:
3 10
4 5 3
3 4 5
1 7 1
输出样例#1:
9 12 12 19 25 29 31 44 45 54
说明
数据规模:n,m<=10000
大家看到函数解析式极其定义域就不难知道,他实际上是给了我们n串排好序的数组,只是每个数组中下标与其值存在一定的对应关系。我们由上面所说的可知,对于每个数组,它们的最小值所在的下标都是1。现在,我们可以想象一下,每个数组都有一个箭头,每个箭头都指向1,然后在所有箭头指向的函数值中,找到最小的那个,此时已经找到了1个最小函数值。接着,刚才输出来的值所对应的箭头就要向后移,指向x=2,然后再去和其他箭头指向的函数值比较,以此类推。
#include <bits/stdc++.h>
using namespace std;
int mn1,mn2;
int A[10005], B[10005], C[10005];
int f[10005];
int n,m;
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d %d %d",&A[i],&B[i],&C[i]);
f[i]=1;
}
for(int i=1;i<=m;i++)
{
mn1=99999999;
for(int j=1;j<=n;j++)
{
if(A[j]*f[j]*f[j]+B[j]*f[j]+C[j]<mn1)
{
mn1=A[j]*f[j]*f[j]+B[j]*f[j]+C[j];
mn2=j;
}
}
printf("%d ",A[mn2]*f[mn2]*f[mn2]+B[mn2]*f[mn2]+C[mn2]);
f[mn2]++;
}
return 0;
}
堆
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=10005;
int n,m;
int t;
int hp[MAXN];
int ans[MAXN];
struct O
{
int a,b,c;
} h[MAXN];
int del()
{ //大根堆
int res=hp[1];
hp[1]=hp[t];
t--;
int now=1;
while(now*2<=t)
{
int tp=now*2;
if(tp<t&&hp[tp]<hp[tp+1])tp++;
if(hp[tp]>hp[now])swap(hp[tp],hp[now]);
else break;
now=tp;
}
return res;
}
bool cmp(O x,O y)
{
return x.c<y.c;
}
void pus(int x)
{
hp[++t]=x;
int now=t;
while(now>1)
{
int tp=now/2;
if(hp[now]>hp[tp])swap(hp[now],hp[tp]);
else break;
now=tp;
}
}
int f(int i,int x)
{
return h[i].a*x*x+h[i].b*x+h[i].c;
}
int main()
{
scanf("%d%d",&n,&m);
memset(hp,0x7f,sizeof hp);
for(register int i=1; i<=n; i++)
scanf("%d%d%d",&h[i].a,&h[i].b,&h[i].c);
sort(h+1,h+n,cmp);
for(register int i=1; i<=n; i++)
for(register int j=1; j<=m; j++)
{
int r=f(i,j);
while(t>m)
del();
if(r<hp[1]||t<m)
pus(r);
else
break;
}
while(t>m)
del();
for(int i=1; i<=m; i++)
ans[i]=del();
for(int i=m; i>=1; i--)
cout<<ans[i]<<" ";
return 0;
}