Summer Vacation

4 篇文章 0 订阅
1 篇文章 0 订阅

题源:https://atcoder.jp/contests/abc137/tasks/abc137_d

Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 400400 points

Problem Statement

There are NN one-off jobs available. If you take the ii-th job and complete it, you will earn the reward of BiBi after AiAi 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 MM days from today.

You can already start working today.

Constraints

  • All values in input are integers.
  • 1≤N≤1051≤N≤105
  • 1≤M≤1051≤M≤105
  • 1≤Ai≤1051≤Ai≤105
  • 1≤Bi≤1041≤Bi≤104

Input

Input is given from Standard Input in the following format:

NN MM
A1A1 B1B1
A2A2 B2B2
⋮⋮
ANAN BNBN

Output

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


Sample Input 1 Copy

Copy

3 4
4 3
4 1
2 2

Sample Output 1 Copy

Copy

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 Copy

Copy

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

Sample Output 2 Copy

Copy

10

Sample Input 3 Copy

Copy

1 1
2 1

Sample Output 3 Copy

Copy

0

题解:

算法:贪心

题意概括:每天最多只能选择一个任务,但每天能同时做多个任务。因此,你需要把天数多的任务放在前面做,并贪心选择天数相同但收益高的任务来做。

解题思路:

首先,定义一个vector容器数组,用来装只能在第i或者第i天之前选择的任务。写一个for循环,从第m天依次往前选择任务。for循环里用了一个优先队列,用来贪心选择报酬最大的那个任务。for循环的内部实现了每次只选第i天可选任务中报酬最大的那个。而且,如果第i天有多个任务可选,而第i天前面没有任务可选,这时,肯定要从第i天的任务中选择若干个任务,优先队列依次取出队头元素,满足了这个条件,个中奥秘,自己体会~~

#include <bits/stdc++.h>

using namespace std;

const int maxn=1e5+10;
const int inf=0x3f3f3f3f;

typedef long long ll;

vector<int> ve[maxn];//vector最好定义在外面,不然可能爆栈

int main()
{
//	freopen("input.txt","r",stdin);
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	
	int n,k;
	cin>>n>>k;
	int a,b;
	for(int i=0;i<n;i++)
	{
		cin>>a>>b;
		if(a>k) continue;//要有这个条件,不然下面的vector可能会成负值
		ve[k-a+1].push_back(b);//表示只能在m-a+1天或者之前做
	}
	priority_queue<int> q;
	int earn=0;
	for(int i=k;i>=1;i--)//注意此处是从第k天开始往前推
	{
		for(int v:ve[i]) q.push(v);
		if(!q.empty())
		{
			earn+=q.top();
			q.pop();
		}
	}
	cout<<earn;
	
	
	return 0;
 } 

为什么上面有一个k'-a+1呢

假如现在有一个任务是3天的,而你的总时间是5天。

那你肯定最晚在第三天完成,5-3+1等于3,,类似的自己可以列举。 

涉及知识点:

1、优先队列默认从大到小排序。

 

打破砂锅问到底。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值