【洛谷2085】最小函数值(堆)

点此看题面
大致题意: 给你(n)个形如(F_i(x)=A_ix^2+B_ix+C_i(A_i,B_i,C_i,x∈N^*))的函数,请你求出所有函数的所有函数值中最小的前(m)个值。

最暴力的解法

显然,我们可以发现一个性质:对于每一个函数,它的值肯定随着(x)的增大而增大

也就是说,最终答案的(x)肯定小于(m),我们就可以考虑对于每一个函数,求出(x=[1..m])时的值,然后将所有的值排序一遍,输出前(m)小的即可。

考虑如何优化

由于上面的那个性质,我们可以发现,对于同一个函数,如果(x=k)时的值是最终的一个答案,那么(x=k-1)时的值显然也是最终的一个答案,因为(x=k-1)时的值是小于(x=k)时的值的。

推广可得,如果(x=k)时的值是最终的一个答案,那么(x=[1..k])时的值都是最终的答案

既然这样,我们又可以得到,只有(x=k-1)时的值是最终的一个答案了,(x=k)时的值才有可能是最终的一个答案

这样一来,我们就可以用堆(优先队列)来进行优化了。

正确的做法:堆

首先,我们将每一个函数(x=1)时的值加入堆中,然后,进行(m)次操作,每次操作取出堆顶的值并将其输出,然后将当前函数的(x)(1)后得到的值重新加入堆中。

我们可以发现,在整个过程中,对于每一个值我们只需要记录三个信息:值的大小属于哪一个函数以及当前的(x)

因为每一次操作的时间复杂度是(O(logn))的,因此总复杂度是(O(mlogn))

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define tc() (A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++)
#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))
#define fi first//减少代码量,用fi表示第一个元素,se表示第二个元素,th表示第三个元素
#define se second.first
#define th second.second
#define N 10000
int pp_=0;char ff[100000],*A=ff,*B=ff,pp[100000];
using namespace std;
int n,m,a[N+5],b[N+5],c[N+5];
typedef pair<int,pair<int,int> > Status;//对于每一个值,需要记录3个信息
priority_queue<Status,vector<Status>,greater<Status> > q;//一个堆(优先队列)
inline void read(int &x)
{
    x=0;int f=1;static char ch;
    while(!isdigit(ch=tc())) f=ch^'-'?1:-1;
    while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
    x*=f;
}
inline void write(int x)
{
    if(x<0) pc('-'),x=-x;
    if(x>9) write(x/10);
    pc(x%10+'0');
}
int main()
{
    register int i;
    for(read(n),read(m),i=1;i<=n;++i) 
        read(a[i]),read(b[i]),read(c[i]),q.push(make_pair(a[i]+b[i]+c[i],make_pair(i,1)));//将每个函数x=1时的值加入堆中
    for(i=1;i<=m;++i)
    {
        Status k=q.top();q.pop();//取出堆顶
        write(k.fi),pc(' '),++k.th,q.push(make_pair(k.th*k.th*a[k.se]+k.th*b[k.se]+c[k.se],make_pair(k.se,k.th)));//输出堆顶的值并将该函数x+1时的值重新加入堆中 
    }
    return fwrite(pp,1,pp_,stdout),0;
}
原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu2085.html