CF1539D PriceFixed[题解]

PriceFixed

题目大意

市场上又 \(n\) 种商品,每种商品的价格都是 \(2\) 。对于第 \(i\) 种商品 \(a_i\) 件。对于商品 \(i\) 给出一个值 \(b_i\) ,如果你已经购买了 \(b_i\) 种商品(购买所有商品的综合),那么你购买这种商品,价格为 \(1\)

求最小代价。

分析

出题人特意标注:每种商品不一定只能购买 \(a_i\) 件。

在引导我们往哪个地方想?——我们可以通过刷已经打折的商品来达到让没有打折的商品打折。

这其实是个坑……

仔细想想,你白花了 \(1\) 点代价,即使打折了,你再买,也根本不会变优。其实无非也就两种情况,你花费一个 \(1\) ,赚到了一个购买量,如果到了 \(b_i\) ,你买,相当于你还是花了 \(2\) ,如果没到,反而你还花了 \(3\) ,将这个例子带到整个里面来看,把一个商品看成“一段”商品,是一样的,这种买法不可能更优

那接下来我们怎么买呢?

贪心!

将每种商品按照 \(b_i\) 排序,\(b_i\) 越大我们越优先买,因为他最不可能打折,接下来按照以下程序:

  • 如果当前 \(b_i\) 最大的商品我们还没有买够,就买,同时注意目前没有买完的商品中 \(b_i\) 最小的数量。

  • 一旦购买量达到任意一个商品的 \(b_i\) ,马上将这种商品买完。

不难证明这种方法一定是最优的。

CODE

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
inline int read()
{
	int s=0,w=1;
	char ch=getchar();
	while(ch<'0'||ch>'9') { if(ch=='-') w*=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
	return s*w;
}
struct node{
	int a,b;
}p[N];
int n,ans;
inline bool cmp(node x,node y) { return x.b>y.b; }
signed main()
{
	n=read();
	for(register int i=1;i<=n;i++) p[i].a=read(),p[i].b=read();
	sort(p+1,p+n+1,cmp);
	int l=1,r=n,sum=0;
	while(l<=r){
		if(sum<p[r].b){
			bool AA=false,BB=false;
			int temp1=sum;
			ans+=2*min(p[l].a,p[r].b-sum); //算价格
			if(p[l].a<=p[r].b-sum) BB=true;
			else AA=true;
			sum+=min(p[l].a,p[r].b-sum);
			if(BB) l++;
			if(AA) p[l].a-=(p[r].b-temp1);
		}
		else { ans+=p[r].a,sum+=p[r].a; r--; }
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2021-07-05 21:14  ╰⋛⋋⊱๑落叶๑⊰⋌⋚╯  阅读(86)  评论(0编辑  收藏  举报