函数

函数

 题解

很简单的一道题,部分分就不做分析了我也没打完。

我们可以考虑贪心,先将每个函数的最小值求出来,算出其值最小时的纵坐标和,若它大于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;
}

谢谢!!!

posted @ 2020-10-28 09:57  StaroForgin  阅读(6)  评论(0)    收藏  举报  来源