AtCoder Beginner Contest 137 D - Summer Vacation

D - Summer Vacation


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 400 points

Problem Statement

There are N one-off jobs available. If you take the i-th job and complete it, you will earn the reward of BiBi after Ai days from the day you do it.

You can take and complete at most one of these jobs in a day.

However, you cannot retake a job that you have already done.

Find the maximum total reward that you can earn no later than M days from today.

You can already start working today.

题意:

有N项工作,每一天你都可以选择一项工作去完成(这些工作你都可以在一天内完成),一天你只能选择完成一项任务,并且不能重复选择已经完成的任务,每完成一个任务,你都可以在A天之后拿到报酬B,问在M天之内你能拿到的最大报酬(超过M天你就拿不到报酬了)。

PS:当时脑抽,题意都看错了,伤心

Constraints

  • All values in input are integers.
  • 1≤N≤10^5
  • 1≤M≤10^5
  • 1≤Ai≤10^5
  • 1≤Bi≤10^4

Input

Input is given from Standard Input in the following format:

NN MM
A1 B1
A2 B2
⋮
AN BN

Output

Print the maximum total reward that you can earn no later than M days from today.


Sample Input 1 

3 4
4 3
4 1
2 2

Sample Output 1 

5

You can earn the total reward of 55 by taking the jobs as follows:

  • Take and complete the first job today. You will earn the reward of 33 after four days from today.
  • Take and complete the third job tomorrow. You will earn the reward of 22 after two days from tomorrow, that is, after three days from today.

Sample Input 2 

5 3
1 2
1 3
1 4
2 1
2 3

Sample Output 2 

10

Sample Input 3 

1 1
2 1

Sample Output 3 

0

思路:

M天,第i天你都选择A不超过M-i+1(确保能拿到报酬)的最大B(报酬最大)的任务就可以得到答案。

以下是某个大佬的代码,借用以下:

#include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


struct FastIO{
  FastIO(){
    cin.tie(0);
    ios::sync_with_stdio(0);
  }
}fastio_beet;

//INSERT ABOVE HERE
signed main(){
  Int n,m;
  cin>>n>>m;
  vector<Int> as(n),bs(n);
  for(Int i=0;i<n;i++) cin>>as[i]>>bs[i];

  vector< vector<Int> > G(m+1);
  for(Int i=0;i<n;i++)//G[i]表示m-i天后,你能拿到报酬的任务有哪些 
    if(as[i]<=m) G[m-as[i]].emplace_back(bs[i]);

  Int ans=0;
  priority_queue<Int> pq;
  for(Int i=m;i>=0;i--){//i从m~0,也就是A从小到大选起
  /*这样子确保了 第j天你选择的任务的A不超过M-j+1(j从1~m)
  为什么呢, 反向思考一下
  最后一天,我们选A不大于1的B最大的一个任务
  倒数第二天,我们可以选A不大于2的B最大的一个任务
  		此时前面A不大于1的任务还有剩的话,当然也可以选
	    只要B最大就可以了
	其余天雷同 
   这样反过来选择就能够达到我们的要求 
  */ 
    for(Int x:G[i]){//每次循环按A从小到大把对应的B加进来 
    	pq.emplace(x);
	}
    if(!pq.empty()){//每次只选B最大的 
      ans+=pq.top();
      pq.pop();
    }
  }
  cout<<ans<<endl;
  return 0;
}

当然正向思考也是可以的,但是我想到的比较麻烦,从头开始,A为m的只能选择一个,而如果没有选择A为m的,A为m-1的就可以选择两个,填补A为m的位置,否则也只能选择一个,其他的情况也是相同的。代码我也没写,感觉比较麻烦。只是记录一下新的思路。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值