题目来源
http://codevs.cn/problem/2913/
题目描述
埃罗芒阿老师是著名的插画家,她的工作是为电击文库出版的的书画插画。 快要到截稿日了,埃罗芒阿老师还在水>_<
埃罗芒阿突然发现自己还有一大堆插画没有完成,如果不能在截稿时间内完成是要扣工资的。
于是埃罗芒阿老师把每个任务所需的时间和现在距离每个任务截稿的时间记录了下来,想要计算出最多可以完成多少任务。输入描述 第一行是一个整数N,
接下来N行每行两个整数T1,T2描述一个任务:完成这个任务需要T1秒,如果在T2秒之内还没有完成任务,这个任务就到截稿时间了。输出描述 输出一个整数S,表示最多可以完成S个任务.
样例输入
4
100 200
200 1300
1000 1250
2000 3200样例输出
3对于30%的数据,N≤100;
对于60%的数据,N≤10000;
对于100%的数据,N < 150,000;
T1 < T2 < INT_MAX; 所有数据保证随机生成。
正解:贪心+堆
首先利用贪心处理处顺序:按截止时间从小到大排序,如果截止时间相同,按需要的时间从小到大排序。(在截止时间相同的情况下,显然需要时间少的更优)。然后我们建个堆,堆顶是花费时间最大的元素。对于这个堆来说,如果一个数据加进来合法,那显然直接加进来即可。否则的话,就把堆顶弹出来,比较大小(显然当不合法的时候,放入一个更小的时间会更优一些)。
代码如下:
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const long long maxn=200005;
struct dqs
{
long long xy,jz;//xy==需要 jz==截止
}hh[maxn];
bool cmp(dqs a,dqs b)
{
if(a.jz==b.jz) return a.xy<b.xy;
return a.jz<b.jz;
}
bool operator <(dqs a,dqs b)
{
return a.xy<b.xy;
}
priority_queue<dqs>q;
int main()
{
long long n;
scanf("%lld",&n);
for(long long i=1;i<=n;i++) scanf("%lld%lld",&hh[i].xy,&hh[i].jz);
sort(hh+1,hh+n+1,cmp);
long long ans=0,tot=0;
for(long long i=1;i<=n;i++)
{
if(hh[i].xy+tot<=hh[i].jz)
{
ans++;
q.push(hh[i]);
tot+=hh[i].xy;
}
else
{
dqs head=q.top();
q.pop();
tot-=head.xy;
if(hh[i].xy<head.xy)
{
q.push(hh[i]);
tot+=hh[i].xy;
}
else
{
q.push(head);
tot+=head.xy;
}
}
}
printf("%lld",ans);
return 0;
}