正题
jzoj题目链接:https://jzoj.net/senior/#main/show/5461
题目大意
有n个物品,m元,k个打折券。
每个物品打折前pip_ipi元,打折后qiq_iqi元,求最多能买多少物品。
解题思路
用可撤回贪心。
先将p和q分开排序,然后前k个都用打折劵。之和我们考虑一个新的东西如果必须打折的话,那么就相当于用pmini−qminip_{min\ i}-q_{min\ i}pmin i−qmin i元买一个打折卷,所以我们用堆用最大的进行比较买不买打折券好
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);
}