您的位置:首页 > 其它

【JZOJ 5461】【NOIP2017提高A组冲刺11.8】购物

2017-11-08 22:26 531 查看

Description

X 城的商场中,有着琳琅满目的各种商品。一日,小X 带着小Y 前来购物,小Y 一共看中了n件商品,每一件商品价格为Pi。小X 现在手中共有m个单位的现金,以及k 张优惠券。小X 可以在购买某件商品时,使用至多一张优惠券,若如此做,该商品的价格会下降至Qi。

小X 希望尽可能多地满足小Y 的愿望,所以小X 想要知道他至多能购买多少件商品。

Solution

二分答案,考虑可行性判定,

用可撤销贪心,

先选q前K小的,

那么,对于选了的,把它变成不选的需要代价p−q,但可以多一个选去的名额

选mid个,看看代价是否小于等于m即可,

复杂度:O(nlog(n)2)

Code

#include <cstdio>
#include <algorithm>
#include <queue>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fod(i,a,b) for(int i=a;i>=b;i--)
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=100500;
int read(int &n)
{
int w=1;n=0;char ch=' ';
for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());
if(ch=='-')ch=getchar(),w=-1;
for(;ch<='9'&&ch>='0';ch=getchar())n=n*10+ch-48;
return n=n*w;
}
int n,K,ans;
LL m;
struct qqww
{
int x,y;
}a
;
struct qwqw
{
int v,i;
friend bool operator<(qwqw q,qwqw w){return q.v>w.v;}
};
priority_queue<qwqw>d,d1;
int z
,TI;
bool PX(qqww q,qqww w){return q.y<w.y;}
LL OK(int mid)
{
LL ans=0;
for(;!d.empty();d.pop());
for(;!d1.empty();d1.pop());
qwqw t;TI++;
fo(i,1,min(K,mid))
{
ans+=(LL)a[i].y;
t.v=a[i].x-a[i].y;
d1.push(t);
z[i]=TI;
}
if(mid<=K)return ans;
fo(i,K+1,n)
{
t.v=a[i].x,t.i=i;d.push(t);
}
int q=K+1;
fo(i,K+1,mid)
{
for(;q<n&&z[q]==TI;q++);
if(!d1.empty()&&d1.top().v+a[q].y<d.top().v)
{
z[q]=TI;
ans+=(LL)d1.top().v+a[q].y;
d1.pop();
q++;
}else
{
t=d.top();d.pop();
ans+=(LL)t.v;
z[t.i]=TI;
}
}
return ans;
}
int main()
{
freopen("shopping.in","r",stdin);
freopen("shopping.out","w",stdout);
int q,w;
read(n),read(K),scanf("%lld",&m);
fo(i,1,n)read(a[i].x),read(a[i].y);
sort(a+1,a+1+n,PX);
int l=0,r=n;
while(l<r)
{
int mid=(l+r+1)>>1;
if(OK(mid)<=m)l=mid;
else r=mid-1;
}
printf("%d\n",l);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: