priotity_queue 洛谷 2707

於是乎,我們要知道了如何要重載定義符!

重載

定義一

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 1

output:
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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章