1. 程式人生 > >【2018/10/01測試T3】【WOJ 4010】購買書籍

【2018/10/01測試T3】【WOJ 4010】購買書籍

【題目】

題目描述:

L 的書籍被 M 偷了以後傷心欲絕,決定再購買一些回來,現在有 N 本書可以買,每本書的價格是 a[ i ]元。

現在 L 總共有 M 元,以及 K 張優惠券。 對於每本書,如果使用一張優惠券,則可以用b[i]的優惠價格購買。 注意每本書只能使用一張優惠券,只能購買一次。

L想知道自己最多可以購買幾本書?

輸入格式:

第一行三個整數 N , K , M

接下來 N 行,每行兩個整數,表示 a[ i ] 和 b[ i ]。

輸出格式:

一個整數表示答案。

樣例資料:

輸入

4 1 7 3 2 2 2 8 1 4 3

輸出

3

備註:

【解釋】

選擇第 1、 2、 3 本書,其中第 3 本使用優惠券。總共 5 元。

【資料規模】

對於 20%:N ≤ 10

對於 50%:N ≤ 100

對於另外 20%:K = 0

對於 100%:1 ≤ N ≤ 100000,0 ≤ K ≤ N,M ≤ 10^{14},1 ≤ b[ i ] ≤ a[ i ] ≤ 10^{9}

【分析】

用一個錯解 A 了,資料太水

對於100%資料: 貪心

先使用K張優惠券,買價格最小的。

如果考慮如何擴充套件當前解 :

1、直接購買一個  a[ i ]  2、退掉一個用優惠券的,用優惠券去買別的  b[ j ] + ( a[ i ] - b[ i ] ) 

2 種情況看哪一個更優 

用堆維護 a[ i ], b[ i ], a[ i ] - b[ i ] 

【程式碼】

大佬的程式碼

#include<bits/stdc++.h>
#define in read()
#define N 100009
#define ll long long
using namespace std;
inline int read(){
	char ch;int res=0;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	} 
	return res;
} 
int n,k,a[N],b[N],id[N];
ll m;
set<pair<int,int> > s1,s2,s3;
bool cmp(int x,int y){return b[x]<b[y];}
int main(){
	n=in;k=in;scanf("%lld",&m);
	for(int i=1;i<=n;++i){
		a[i]=in;b[i]=in;
		id[i]=i;
	}
	sort(id+1,id+n+1,cmp);
	if(k==0){//特殊的特判一下
		sort(a+1,a+n+1);ll sum=0;
		for(int i=1;i<=n;++i){
			sum+=a[i];
			if(sum>m) {
				printf("%d",i-1);
				return 0;
			}
		}
		printf("%d",n);
		return 0;
	}
	ll now=0;int ans=0;
	for(int i=1;i<=k;++i){
		now+=b[id[i]];if(now>m) {	return printf("%d",ans),0;	}
		++ans;
		s1.insert(make_pair(a[id[i]]-b[id[i]],id[i]));//差值
	}
	for(int i=k+1;i<=n;++i){
		s2.insert(make_pair(b[id[i]],id[i]));//優惠價
		s3.insert(make_pair(a[id[i]],id[i]));//原價
	}
	while(s2.size()){
		ll f1=s1.begin()->first+s2.begin()->first,f2=s3.begin()->first;
		if(f1<f2){
			now+=f1;if(now>m) 	return printf("%d",ans),0;
			ans++;int u=s2.begin()->second;
			s1.erase(s1.begin());s2.erase(s2.begin());
			s1.insert(make_pair(a[u]-b[u],u));s3.erase(s3.find(make_pair(a[u],u)));
		}
		else{
			now+=f2;if(now>m) 	return printf("%d",ans),0;
			ans++;int u=s3.begin()->second;
			s3.erase(s3.begin());s2.erase(s2.find(make_pair(b[u],u)));
		}
	}
	printf("%d",ans);
	return 0;
}