Educational Codeforces Round 62 (Rated for Div. 2) C. Playlist 贪心+优先队列

You have a playlist consisting of nn songs. The ii-th song is characterized by two numbers titi and bibi — its length and beauty respectively. The pleasure of listening to set of songs is equal to the total length of the songs in the set multiplied by the minimum beauty among them. For example, the pleasure of listening to a set of 33 songs having lengths [5,7,4][5,7,4] and beauty values [11,14,6][11,14,6] is equal to (5+7+4)⋅6=96(5+7+4)⋅6=96.You need to choose at most kk songs from your playlist, so the pleasure of listening to the set of these songs them is maximum possible.

Input
The first line contains two integers nn and kk (1≤k≤n≤3⋅1051≤k≤n≤3⋅105) – the number of songs in the playlist and the maximum number of songs you can choose, respectively.Each of the next nn lines contains two integers titi and bibi (1≤ti,bi≤1061≤ti,bi≤106) — the length and beauty of ii-th song.

Output
Print one integer — the maximum pleasure you can get.

Examples


input

4 3
4 7
15 1
3 6
6 8

output

78



input

5 3
12 31
112 4
100 100
13 55
55 50

output

10000



Note
In the first test case we can choose songs 1,3,41,3,4, so the total pleasure is (4+3+6)⋅6=78(4+3+6)⋅6=78.In the second test case we can choose song 33. The total pleasure will be equal to 100⋅100=10000100⋅100=10000.

昨天晚上写的,没想出来,头疼得连水题都写得特别慢,今天肯定又得掉分了。

题目大意是给我们n首歌曲,每首歌都有两个特征:美丽值和时长。让我们选择至多k首歌组成一个播放列表,让这个播放列表的“舒坦值”最高,舒坦值的计算是,集合中所有歌曲的播放时长之和,乘以集合中歌曲的最小价值。

pleasure=max(timesum)*min(beauty in song set)

考场上我没想明白,后来看了几份代码,才发现是这么做:

  1. 就是对所有的歌曲按美丽值升序排列。
  2. 创建一个小根堆,存时长相对大的歌曲。初始为空。
  3. 从所有排序过的歌曲中,从后向前遍历,加入小根堆中,并记录当前堆中的歌曲时间和sum。如果小根堆size小于k则可以接着加,如果大于k,则pop栈顶元素,并且sum-对应值。对每次尝试加入操作,都计算sum*beauty[i],就是当前歌曲美丽值和sum的乘积,这个值得最大值就是我们的答案。

由于我们已经按美丽值对歌曲升序排序,所以从后向前遍历,美丽值肯定在下降,也就是说每次遍历,都取到了能取到的最大beauty值,并且由于小根堆的存在,所以我们的时长sum值也总是当前情况下的最大值,则遍历完整个歌曲集合后,得到的结果就是答案。

下面是代码。


#include <bits/stdc++.h>
#define N 300010
using namespace std;
typedef pair<int,int> p;
typedef long long ll;
p song[N];
ll n,k,sum,ans;void attemptAdd(int c);priority_queue<int,vector<int>,greater<int> > q;int main()  {
    cin>>n>>k;
    for (int i=0;i<n;i++)
        cin>>song[i].second>>song[i].first;
    sort(song,song+n);
    for (int i=n-1;i>=0;i--)    {
        attemptAdd(song[i].second);
        ans=max(ans,sum*song[i].first);
    }
    cout<<ans<<endl;
    return 0;}

void attemptAdd(int c)   {
    q.push(c);
    sum+=c;
    if ((int)q.size()>k)    {
        sum-=q.top();
        q.pop();
    }}

单从本题看,有这样的一个结论:ans=变化值*最值,则可以对最值排序,让每次取最优,然后对变化值用数据结构维护,也每次取最优,则结果就是最优值。

猜你喜欢

转载自www.cnblogs.com/yichuan-sun/p/10585091.html