题目
求前 m m m个最小函数值
分析
用堆实现,首先把每一种函数的最小值 ( x = 1 ) (x=1) (x=1)加入堆,再把这种函数增加1。
优先队列STL代码
#include <cstdio>
#include <cctype>
#include <queue>
#define M 10001
#define yi p.first
#define er p.second
using namespace std;
priority_queue <pair<int,int> >heap;
int a[M],b[M],c[M],now[M],n,m;
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int main(){
n=in(); m=in();
for (int i=1;i<=n;i++)
a[i]=in(),b[i]=in(),c[i]=in(),now[i]=1,heap.push(make_pair(-a[i]-b[i]-c[i],i));//小根堆
for (int i=1;i<=m;i++){
pair<int,int>p=heap.top(); //弹出
heap.pop(); printf("%d ",-yi);//小根堆时改变符号,so取相反数
int x=++now[er];//现在这个函数的x增加
heap.push(make_pair(-a[er]*x*x-b[er]*x-c[er],er));//插入
}
return 0;
}
小根堆代码
#include <cstdio>
#include <cctype>
#include <algorithm>
#define M 10010
using namespace std;
struct dui{int val,num;}heap[M];
int a[M],b[M],c[M],now[M],n,m;
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void up(int x){while (x>1&&heap[x].val<heap[x>>1].val) swap(heap[x],heap[x>>1]),x>>=1;}
void down(int x){ int y;
while ((x<<1)<=n){
if ((x<<1)==n||heap[x<<1].val<heap[(x<<1)+1].val) y=x<<1; else y=(x<<1)+1;
if (heap[x].val>heap[y].val) swap(heap[x],heap[y]); x=y;
}
}
int main(){
n=in(); m=in();
for (int i=1;i<=n;i++)
a[i]=in(),b[i]=in(),c[i]=in(),now[i]=1,
heap[i].num=i,heap[i].val=a[i]+b[i]+c[i],up(i);//上移
for (int i=1;i<=m;i++){
printf("%d ",heap[1].val);
int x=++now[heap[1].num];//增加
heap[1].val=a[heap[1].num]*x*x+b[heap[1].num]*x+c[heap[1].num];//改变
down(1);//下移
}
return 0;
}