于是乎,我们要知道了如何要重载定义符!
重载
定义一
friend bool operator < (number x,number y)
{
return x.val<y.val;// 这是大根堆的应用!
}
定义二
bool operator < (number &x) const
{
return ...;
}
题面:
Facer的父亲是一名经理,现在总是垂头丧气的。
Facer问父亲,怎么啦?父亲说,公司出了点问题啊。
公司管理着N个风景点,每个风景点都有不少人来参观。
可是现在!人民投诉票价太高了,他不得不调整票价
具体来说,第i个景点如果票价是x,来的人数就是max( (ai - bi * x),0 )[收益自己算好伐]
你需要分配每个景点的门票,使得每个景点门票总和不超过k,且最大化收益=
求最大的收益input:
2 4
50 2
40 1output:
171
解释:
景点1票价3,景点2票价1
景点1人数:50 - 3*2 = 44 票价 :3 收益:132
景点2人数 : 40 - 1*1 = 39 票价 : 1 收益:39
总收益171 最大
思路:
我们其实会发现,对于每一个函数的值如果增长了 1 之后,对于答案的贡献就会增加一个表达的值!
就像这样!:
于是每一次在开一个堆,将增量分别推进大根堆里面!
每一次取出的时候就是只要将这个函数的x+1就好了,别的函数的治病不需要变!
具体就增量就是可以直接来求导一发就好了!
具体看代码
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 101000;
int n,k;
ll ans,a[N],b[N];
struct node
{
int x,id;
long long add;
friend bool operator < (node first,node second)
{
return first.add < second.add;
}
} make;
priority_queue<node> final;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1; i<=n; i++)
scanf("%d%d",&a[i],&b[i]);
for(int i=1; i<=n; i++)
{
make.x=1,make.add=a[i]+b[i]-2*b[i],make.id=i;
final.push(make);
}
for(int v=1; v<=k; v++)
{
node num=final.top();final.pop();
if(num.add<0) break;
ans+=num.add;
num.x++,num.add=a[num.id]+b[num.id]-2*b[num.id]*num.x;
final.push(num);
}
printf("%lld\n",ans);
}