nssl1148,jzoj5461-購物【可撤回貪心,堆】
阿新 • • 發佈:2018-12-10
正題
題目大意
有n個物品,m元,k個打折券。 每個物品打折前元,打折後元,求最多能買多少物品。
解題思路
用可撤回貪心。 先將p和q分開排序,然後前k個都用打折劵。之和我們考慮一個新的東西如果必須打折的話,那麼就相當於用元買一個打折卷,所以我們用堆用最大的進行比較買不買打折券好
code
#include<cstdio>
#include<algorithm>
#include<queue>
#define N 100010
using namespace std;
struct node{
long long w,num;
}q[N] ,p[N];
long long n,k,m,ans;
priority_queue <int> K;
bool f[N];
bool cmp(node x,node y)
{return x.w<y.w;}
int main()
{
scanf("%lld%lld%lld",&n,&k,&m);
for(long long i=1;i<=n;i++)
{
scanf("%lld%lld",&p[i].w,&q[i].w);
p[i].num=q[i].num=i;
}
sort (p+1,p+1+n,cmp);
sort(q+1,q+1+n,cmp);//分開排序
long long j=1;
for(long long i=1;i<=n;i++)
{
if(k)//前k個全要
{
if(m>=q[i].w)
{
m-=q[i].w;
f[q[i].num]=true;
K.push(q[i].w-p[q[i].num].w);
ans++;k--;
}
}
else
{
while(f[j]&&j<n)j++;//走到沒有用過的
if(m>=min(p[j].w,q[i].w-K.top()))//買的起
{
m-=min(p[j].w,q[i].w-K.top());
if(p[j].w>q[i].w-K.top())
{
m-=q[i].w-K.top();
K.pop();
K.push(q[i].w-p[q[i].num].w);//壓入堆
}
else j++;//下一個最小的
ans++;//多買一個
}
}
}
printf("%lld",ans);
}