函数
函数
题解
很简单的一道题,部分分就不做分析了我也没打完。
我们可以考虑贪心,先将每个函数的最小值求出来,算出其值最小时的纵坐标和,若它大于m则将每次移一位可以更小的不断左移,直到和变为m,反之亦然。因为a必定大于0,很容易证明,这样得出的答案为最优的。
注意,要freopen的。
源码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#define MAXN 100005
using namespace std;
typedef long long LL;
#define int LL
const LL INF=0x7f7f7f7f7f7f;
LL n,m,cnt[MAXN],a[MAXN],b[MAXN],c[MAXN],sum,ans;
struct ming
{
int cz,id;
bool friend operator < (const ming &x,const ming &y){
if(x.cz<y.cz) return 0;
return 1;
}
};
priority_queue<ming> q;
#define gc() getchar()
template<typename _T>
inline void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
LL F(LL i,LL j){
return a[i]*j*j+b[i]*j+c[i];
}
signed main(){
freopen("function.in","r",stdin);
freopen("function.out","w",stdout);
read(n);read(m);
for(int i=1;i<=n;i++){
read(a[i]);read(b[i]);read(c[i]);
LL tmp=-(b[i])/(2ll*a[i]);
if(F(i,tmp)>F(i,tmp+1)) tmp=tmp+1;
if(tmp<=0) tmp=1LL;
cnt[i]=tmp;sum+=tmp;
}
if(sum>m){
for(int i=1;i<=n;i++){
ming t;
t.cz=F(i,cnt[i]-1LL)-F(i,cnt[i]);
t.id=i;q.push(t);
}
while(sum>m){
ming t1=q.top();q.pop();
if(cnt[t1.id]<2LL) continue;
cnt[t1.id]--;sum--;
ming t2;t2.id=t1.id;
t2.cz=F(t1.id,cnt[t1.id]-1LL)-F(t1.id,cnt[t1.id]);
q.push(t2);
}
}
else if(sum<m){
for(int i=1;i<=n;i++){
ming t;
t.cz=F(i,cnt[i]+1)-F(i,cnt[i]);
t.id=i;q.push(t);
}
while(sum<m&&!q.empty()){
ming t1=q.top();q.pop();
//printf("%lld %lld\n",t1.id,t1.cz);
cnt[t1.id]++;sum++;
ming t2;t2.id=t1.id;
t2.cz=F(t1.id,cnt[t1.id]+1LL)-F(t1.id,cnt[t1.id]);
q.push(t2);
}
}
for(int i=1;i<=n;i++)
ans+=F(i,cnt[i]);
printf("%lld",ans);
return 0;
}