HDU 6546 ( 贪心 )

HDU 6546 ( 贪心 )

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6546

题意:有n个二次函数,给每个函数选择一个值x,让所选x值的和正好等于m,问此时f(x)的最小值是多少。

思路:为了满足最小值的要求,我们先假设所有函数就选择 -b/(2*a) 的最小值点,然后我们看一下这样选择后是比m大还是小,如果小,我们就让所选的pos增加,是必然的答案也会增加,所以我们需要选择n个函数里增幅最小的那个。用优先队列维护。

优化:注意到所选x必须是正整数,所以我们就全初始化为1。这样我们就只需要维护增加的部分,减小的部分就不用维护了。

注意:以后做题还是要想好再开始写代码,不然找bug真的太绝望了。

代码:

#include <bits/stdc++.h>
#define int long long

using namespace std;

struct node {
    int a,b,c;
    int pos;
}f[100005];
struct nod {
    int a,b,c,pos,id;
    int want;
}up;

bool operator<( const nod &a, const nod &b  )
{
    return a.want>b.want;
}

int n,m,sum;
priority_queue<nod> Qu;

signed main()
{
    cin >> n >> m;
    sum = 0;
    while ( !Qu.empty() ) Qu.pop();
    for ( int i=0; i<n; i++ ) {
        scanf("%lld %lld %lld",&f[i].a,&f[i].b,&f[i].c);
        f[i].pos = 1;
        sum += f[i].pos;

        up.a=f[i].a;up.b=f[i].b;up.c=f[i].c;up.pos=f[i].pos;up.id=i;up.want=0;
        up.want = up.a*(up.pos+1)*(up.pos+1) + up.b*(up.pos+1) + up.c;
        up.want -= (up.a*(up.pos)*(up.pos) + up.b*(up.pos) + up.c);
        Qu.push(up);
    }

    while ( sum<m && !Qu.empty() ) {
        up = Qu.top(); Qu.pop();
        up.pos++; sum++;
        f[up.id].pos ++;
        up.want = 0;
        up.want = up.a*(up.pos+1)*(up.pos+1) + up.b*(up.pos+1) + up.c;
        up.want -= (up.a*(up.pos)*(up.pos) + up.b*(up.pos) + up.c);
        Qu.push(up);
    }
    int ans = 0;
    for ( int i=0; i<n; i++ ) {
        ans += ( f[i].a*f[i].pos*f[i].pos + f[i].b*f[i].pos + f[i].c );
    }
    cout << ans << endl;


    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值