T1 题意简述:jzoj5461
解题思路:贪心。
考虑先用完k张优惠券,只需将商品按优惠价排序,依次判断钱是否足够,若是则ans++,否则直接退
出循环并输出ans即可。
k张优惠券用完后若钱还未用完,则考虑用前面商品的优惠券买后面的商品。注意要把未买的商品按
原价重新排序。只需把用了优惠券的商品的原价与优惠价之差价放进一个小根堆,每次判断:此商品
原价是否小于堆顶商品差价+此商品优惠价。若是则直接用原价买即可,否则用堆顶商品差价+此商品
优惠价买即可。注意有0张优惠券的情况,因此要特判队列是否为空,若是则直接用原价买即可。
由于本蒟蒻及ErkkiErkko大佬均认为把商品按原价重新排序的方法有误,故欢迎各位大佬前来Hack。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #include<vector> #define INF 0x3f3f3f3f #define ll long long using namespace std; ll n,k,m,ans; priority_queue<ll,vector<ll>,greater<ll> > que; struct uio{ ll val,fre; }war[50001]; bool cmp(uio x,uio y) { if(x.fre==y.fre) return x.val<y.val; return x.fre<y.fre; } bool cmp1(uio x,uio y) { return x.val<y.val; } int main() { freopen("shopping.in","r",stdin); freopen("shopping.out","w",stdout); scanf("%lld%lld%lld",&n,&k,&m); for(ll i=1;i<=n;i++) scanf("%lld%lld",&war[i].val,&war[i].fre); sort(war+1,war+1+n,cmp); for(ll i=1;i<=k;i++) { que.push(war[i].val-war[i].fre); if(m>=war[i].fre) m-=war[i].fre,ans++; } sort(war+1+k,war+1+n,cmp1); for(ll i=k+1;i<=n;i++) { if(m>=war[i].val&&(que.empty()||que.top()>war[i].val-war[i].fre)) m-=war[i].val,ans++; else if(!que.empty()&&m>=war[i].fre+que.top()) m-=war[i].fre+que.top(),ans++,que.pop(),que.push(war[i].val-war[i].fre); } printf("%lld\n",ans); return 0; }
T2 题意简述:jzoj5455
解题思路:
原文地址:https://www.cnblogs.com/water-radish/p/9439386.html
时间: 2024-11-02 08:03:47