原题:
题目描述
马上假期就要到了,THU的神犇Leopard假期里都不忘学霸,现在有好多门功课,每门功课都耗费他1单位时间来学习。
他的假期从0时刻开始,有1000000000个单位时间(囧rz)。在任意时刻,他都可以任意一门功课(编号1~n)来学习。
因为他在每个单位时间只能学习一门功课,而每门功课又都有一个截止日期,所以他很难完成所有n门功课。
对于第i门功课,有一个截止时间Di,若他能学完这门功课,他能够获得知识Pi。
在给定的功课和截止时间下,Leopard能够获得的知识最多为多少呢?
他的假期从0时刻开始,有1000000000个单位时间(囧rz)。在任意时刻,他都可以任意一门功课(编号1~n)来学习。
因为他在每个单位时间只能学习一门功课,而每门功课又都有一个截止日期,所以他很难完成所有n门功课。
对于第i门功课,有一个截止时间Di,若他能学完这门功课,他能够获得知识Pi。
在给定的功课和截止时间下,Leopard能够获得的知识最多为多少呢?
输入
第一行,一个整数n,表示功课的数目
接下来n行,每行两个整数,Di和Pi
接下来n行,每行两个整数,Di和Pi
输出
输出一行一个整数,表示最多学得的知识数
样例输入
3
2 10
1 5
1 7
样例输出
17
【样例说明】
第一个单位时间学习第3个功课(1,7),然后在第二个单位时间学习第1个功课(2,10)
数据范围限制
10% n<=25
60% n<10000
100% 1<=n<=100000,Di、Pi<=1000000000
最后的答案可能超过32位整型。
60% n<10000
100% 1<=n<=100000,Di、Pi<=1000000000
最后的答案可能超过32位整型。
思路不说,详见: 我是快乐的老秃驴。
本来说用个小根堆优化,然后打算肝一晚上把小根堆学会的。然后在某位巨佬的指点下,搜索了一个叫优先队列的东西,然后出现一个神奇无比的东西,详见:
转码链接。
对,就是这个:priority_queue <int,vector<int>,greater<int> > q ; !!!优先队列!!!
然后完美的干掉了堆优化,逐渐上手了这个小东西。
当然,要注意的是:我们贪心的时候不能一个一个时间找,因为d很大,所以会爆炸。我们应该直接考虑优先队列的大小,然后进行比较,插入弹出。
见代码
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> using namespace std; int n; long long ans; priority_queue<int,vector<int>,greater<int> >q; struct study{ int d,p; }; study a[100001]; bool cmp1(study x,study y) { return x.d <y.d ; } bool CMP(study x,study y) { return x.p<y.p; } int main() { freopen("study.in","r",stdin); freopen("study.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&a[i].d,&a[i].p); sort(a+1,a+1+n,cmp1); for(int i=1;i<=n;i++) { bool g=false; if(a[i].d<=q.size()) { if(q.top()<a[i].p) { ans-=q.top(); q.pop(); q.push(a[i].p); ans+=a[i].p; } } else { q.push(a[i].p); ans+=a[i].p; } } printf("%lld",ans); return 0; }