C - Function HDU - 6546
由于a大于0,所有二次函数均是开口向上,而且x必须正整数。所以很自然想到先全部分配1.
然后逐个分配,由于二次函数f[i]-f[i-1]左边一定比右边更优,即i越小结果越小。
所以我们可以直接把F[I]-F[I-1]丢到优先队列里。每次让某一个二次函数的x+1,根据前面的分析,一定是队列首的二次函数加1 更优,因为队列里的所有数,将来只可能更大,不会变小。
然后把F[I+1]-F[I]丢回去即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M=1e5+7;
struct node
{
ll f,x,id;
bool operator <(const node &r)const
{
return f>r.f;
}
}p;
priority_queue<node>q;//逆序规则,变成小根堆
int a[M],b[M],c[M];
ll s(int k,int x)
{
return 1LL*a[k]*x*x+1LL*b[k]*x+c[k];
}
int main()
{
int n,m;
cin>>n>>m;
ll ans=0;
for(int i=1;i<=n;i++)
cin>>a[i]>>b[i]>>c[i],ans+=s(i,1),q.push(node{s(i,2)-s(i,1),2,i});
m-=n;
while(m)
{
node tp=q.top();q.pop();
ans+=tp.f;
q.push(node{s(tp.id,tp.x+1)-s(tp.id,tp.x),tp.x+1,tp.id});
m--;
}
cout<<ans<<endl;
return 0;
}
D - Tree