题目描述
有一个商店有许多批货,每一批货又有N(0<=N<= 10^4104 )个商品,同时每一样商品都有收益 P_iPi ,和过期时间 D_iDi (1<= Pi,DiPi,Di <= 10^4104 ),一旦超过了过期时间,商品就不能再卖。
你要做的就是求出每批货最多能得到多少收益。
输入输出格式
输入格式
多组数据,每组先给出一个整数N,表示这批货的商品个数。
然后有N对数,每对数有两个用空格隔开的正整数 P_i,D_iPi,Di ,表示第i个商品的收益和过期时间。相邻两对数之间用空格隔开。
输入以一个文件终止符结束,并且保证所有输入数据正确。
输出格式
对于每组数据,输出一行一个整数表示该批货物能卖出的最大价格。
感谢@Rye_Catcher 提供的翻译
题目描述
输入输出格式
输入格式:
输出格式:
输入输出样例
Solution:
本题贪心。。。
一个很简单的想法就是尽可能的让价值大的先卖,并且尽可能地在时间快要超过限制时卖(很显然,这样能给前面提供更多的选择)。
但是这样的话是$n^2$的,多组数据有点虚。
于是,我们换汤不换药,改成用堆去动态维护。
先将物品按限制时间从小到大排序,再以价值为关键字建立小根堆,然后判断(设$tot$为堆中元素个数):
1、若$t[i].d>tot$,说明当前只用了$tot$天,选$t[i]$不会过期,则直接将$t[i]$加入堆中。
2、若$s[i].d==tot$,说明当前用了$tot$天,选$t[i]$恰好过期,所以与堆顶的元素价值比较,若堆顶价值$<t[i].p$则弹出堆顶将$t[i]$入堆,否则就不操作。
最后输出堆中元素价值之和就好了。
代码:
#include<bits/stdc++.h> #define il inline #define ll long long #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)>(b)?(b):(a)) using namespace std; const int N=100005,inf=233333333; int n,m; struct node{ int p,d; bool operator <(const node &a) const {return p>a.p;} }t[N]; priority_queue<node>q; il bool cmp(const node &a,const node &b){return a.d<b.d;} il int gi(){ int a=0;char x=getchar();bool f=0; while((x<'0'||x>'9')&&x!='-')x=getchar(); if(x=='-')x=getchar(),f=1; while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar(); return f?-a:a; } int main(){ while(scanf("%d",&n)==1){ For(i,1,n) t[i].p=gi(),t[i].d=gi(); sort(t+1,t+n+1,cmp); int tot=0,ans=0; For(i,1,n) if(t[i].d>tot)q.push(t[i]),tot++; else if(t[i].d==tot) { if(t[i].p>q.top().p)q.pop(),q.push(t[i]); } while(tot--)ans+=q.top().p,q.pop(); printf("%d ",ans); } return 0; }