题目:https://www.luogu.org/problemnew/show/P2085
或者http://www.sqyoj.club/problem.php?id=1021
分析:首先,每个二次函数在x>0上单调递增;
其次,用大根堆,把第一个函数的m个函数值存入。从第二个函数开始,如果函数值比结点值小,则存入大根堆。
说明:为什么不用小根堆?答:对于小根堆而言,最大元素未必在堆尾。(用小根堆,卡9个点)
AC代码:
#include<cstdio>
#include<iostream>
using namespace std;
int n,m,A,B,C;
int cnt,now,nxt;
int x,y,a[10005],ans[10005];
int f(int x){
return A*x*x+B*x+C;
}
void swap(int &a,int &b){
int tmp=a;
a=b;
b=tmp;
}
void put(int x){
a[++cnt]=x;
now=cnt;
while(now>1){
nxt=now/2;
if(a[nxt]>=a[now])break;
swap(a[now],a[nxt]);
now=nxt;
}
}
int get(){
int tmp=a[1];
a[1]=a[cnt--];
now=1;
while(now*2<=cnt){
nxt=now*2;
if(nxt<cnt && a[nxt+1]>a[nxt])nxt++;
if(a[now]>=a[nxt])break;
swap(a[now],a[nxt]);
now=nxt;
}
return tmp;
}
int main(){
cin>>n>>m;
cin>>A>>B>>C;
for(int i=1;i<=m;i++){
int y=f(i);
put(y);
}
for(int i=2;i<=n;i++){
cin>>A>>B>>C;
int x=1;
while(x<=m){
int y=f(x);
if(y>=a[1])break;
get();
put(y);
x++;
}
}
for(int i=1;i<=m;i++)
ans[i]=get();
for(int i=m;i>1;i--)cout<<ans[i]<<' ';
cout<<ans[1];
return 0;
}