[LUOGU2085] 最小函數值

題目描述

有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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章