微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

【经典】有K张折扣券和m元最多能买多少物品折前价ai,折后价bi

这真是很玄学的一道题,贪心也要贪好几次。。。

题解:http://www.voidcn.com/article/p-eincjhrs-rv.html

题解:http://www.voidcn.com/article/p-yrbutkck-up.html

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct node{
	int a,b;
}x[100005];
struct node2{
	int a,b,c;
}y[100005],z[100005];
int vis[100005];
int cmp1(node a,node b){
	if(a.b!=b.b)
		return a.b<b.b;
	return a.a<b.a;
}
int cmp2(node2 a,node2 b){
	if(a.b!=b.b)
		return a.b<b.b;
	if(a.a!=b.a)
		return a.a<b.a;
	return a.c<b.c;
}
int cmp3(node2 a,node2 b){
	if(a.a!=b.a)
		return a.a<b.a;
	if(a.b!=b.b)
		return a.b<b.b;
	return a.c<b.c;
}
struct cmp{  
   bool operator()(const int &t1,const int &t2){  
        return t1>t2;  //从小到大,与数组规则相反   
   }
};  
int main(){
	int t;
	cin>>t;
	while(t--){
		priority_queue<node,vector<int>,cmp> q; 
		int n,k;
		ll m;
		cin>>n>>k>>m;
		for(int i=0;i<n;++i){
			cin>>x[i].a>>x[i].b;
		}
		sort(x,x+n,cmp1); //按b排序 
		ll s=0;
		int p=0;
		for(int i=0;i<k;++i){
			s+=x[i].b;
			if(s>m)
				break;
			p++;
		}
		if(s>m){
			cout<<p<<endl;
			continue;
		}
		for(int i=0;i<k;++i){
			q.push(x[i].a-x[i].b);
		}
		for(int i=k;i<n;++i){
			y[i-k]={x[i].a,x[i].b,i-k};
			z[i-k]={x[i].a,i-k};
		}
		sort(y,y+(n-k),cmp3); //按a排序 
		sort(z,z+(n-k),cmp2); //按b排序 
		memset(vis,sizeof(vis));
		int a=0,b=0; 
		for(int i=0;i<n-k;++i){
			while(vis[y[a].c]) a++;
			while(vis[z[b].c]) b++;
			if(!q.empty()){
				int fr=q.top();
				if(z[b].b+fr<=y[a].a){ //比较【折前价最低】和【转移折扣券补差价】哪个低
					s+=z[b].b+fr;
					if(s>m) break;
					p++;
					q.pop();
					q.push(z[b].a-z[b].b);
					vis[z[b].c]=1;
				}
				else{
					s+=y[a].a;
					if(s>m) break;
					p++;
					vis[y[a].c]=1;
				}
			}
			else{ //这个情况不要忽略(k=0时队列为空) 
				s+=y[a].a;
				if(s>m) break;
				p++;
				vis[y[a].c]=1;
			}
		}
		cout<<p<<endl;
	}
	return 0;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐