題目描述
有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;
}