POJ1456 Supermarket
A supermarket has a set Prod of products on sale. It earns a profit px for each product x∈Prod sold by a deadline dx that is measured as an integral number of time units starting from the moment the sale begins. Each product takes precisely one unit of time for being sold. A selling schedule is an ordered subset of products Sell ≤ Prod such that the selling of each product x∈Sell, according to the ordering of Sell, completes before the deadline dx or just when dx expires. The profit of the selling schedule is Profit(Sell)=Σx∈Sellpx. An optimal selling schedule is a schedule with a maximum profit.
For example, consider the products Prod={a,b,c,d} with (pa,da)=(50,2), (pb,db)=(10,1), (pc,dc)=(20,2), and (pd,dd)=(30,1). The possible selling schedules are listed in table 1. For instance, the schedule Sell={d,a} shows that the selling of product d starts at time 0 and ends at time 1, while the selling of product a starts at time 1 and ends at time 2. Each of these products is sold by its deadline. Sell is the optimal schedule and its profit is 80.
Write a program that reads sets of products from an input text file and computes the profit of an optimal selling schedule for each set of products.
0 <= n <= 10000
贪心策略:在最优解中,在不过期的前提下,前t天应该尽量卖出利润前t大的商品。因此,我们可以一次考虑每个商品,动态维护一个满足上述性质的方案。
详细地说,我们把商品按照过期时间排序,建立一个初始为空的小根堆(节点权值为商品利润),然后扫描每个商品。
- 若当前商品的过期时间等于当前堆中的商品个数,且权值大于根权值,则替换掉堆顶。
- 若当前商品的过期时间大于当前堆中的商品个数,直接入堆即可。
最后答案就是堆中的权值之和。
感觉这么做是对的原因是堆中元素的个数只能小于等于当前元素的过期天数。
时间复杂度\(O(n \log n)\)
#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;
rg char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') w=-1;
ch=getchar();
}
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return data*w;
}
template<class T>il T read(rg T&x){
return x=read<T>();
}
typedef long long ll;
using namespace std;
co int N=1e4+1;
namespace T{
int heap[N],n;
void up(int p){
while(p>1){
if(heap[p]<heap[p/2]){
swap(heap[p],heap[p/2]);
p/=2;
}
else break;
}
}
void Insert(int v){
heap[++n]=v;
up(n);
}
void down(int p){
int s=p*2;
while(s<=n){
if(s<n&&heap[s]>heap[s+1]) ++s;
if(heap[s]<heap[p]){
swap(heap[s],heap[p]);
p=s,s=p*2;
}
else break;
}
}
void Extract(){
heap[1]=heap[n--];
down(1);
}
void Remove(int k){
heap[k]=heap[n--];
up(k),down(k);
}
}
struct node{
int p,d;
bool operator<(co node&a)co{
return d<a.d;
}
}a[N];
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n;
while(~scanf("%d",&n)){
T::n=0;
for(int i=1;i<=n;++i)
read(a[i].p),read(a[i].d);
sort(a+1,a+n+1);
for(int i=1;i<=n;++i){
if(T::n<a[i].d) T::Insert(a[i].p);
else if(T::heap[1]<a[i].p) T::Extract(),T::Insert(a[i].p);
}
int ans=0;
for(int i=1;i<=T::n;++i)
ans+=T::heap[i];
printf("%d\n",ans);
}
return 0;
}