CF609D Gadgets for dollars and pounds (#二分答案+贪心)

32 篇文章 2 订阅
9 篇文章 0 订阅

题意翻译

描述 一个人手上有s卢布,他要在n天内买m样东西中的k样. 有两种支付方式,每个物品有一种支付方式,要么用美元,要么用英镑。每天有不同的支付方式代价,即换取一美元或英镑,需要付出x[i]卢布的代价。 要求:最早完成买k样东西的天数。如果无法完成任务,输出-1 一种商品只能购买一次,但是一天可以买多种商品 输入 第1行:n, m, k, s 第2行:n个整数,表示多少卢布换一美元 第3行:n个整数,表示多少卢布换一英镑 接下来是m行,每行2个整数,表示每样东西用什么货币结账(1是美元,2是英镑),以及要多少那种外币 输出 输出最短到第几天买完k样商品

题目描述

Nura wants to buy kk gadgets. She has only ss burles for that. She can buy each gadget for dollars or for pounds. So each gadget is selling only for some type of currency. The type of currency and the cost in that currency are not changing.

Nura can buy gadgets for nn days. For each day you know the exchange rates of dollar and pound, so you know the cost of conversion burles to dollars or to pounds.

Each day (from 11 to nn ) Nura can buy some gadgets by current exchange rate. Each day she can buy any gadgets she wants, but each gadget can be bought no more than once during nn days.

Help Nura to find the minimum day index when she will have kk gadgets. Nura always pays with burles, which are converted according to the exchange rate of the purchase day. Nura can't buy dollars or pounds, she always stores only burles. Gadgets are numbered with integers from 11 to mm in order of their appearing in input.

输入格式

First line contains four integers n,m,k,sn,m,k,s ( 1<=n<=2·10^{5},1<=k<=m<=2·10^{5},1<=s<=10^{9}1<=n<=2⋅105,1<=k<=m<=2⋅105,1<=s<=109 ) — number of days, total number and required number of gadgets, number of burles Nura has.

Second line contains nn integers a_{i}ai​ ( 1<=a_{i}<=10^{6}1<=ai​<=106 ) — the cost of one dollar in burles on ii -th day.

Third line contains nn integers b_{i}bi​ ( 1<=b_{i}<=10^{6}1<=bi​<=106 ) — the cost of one pound in burles on ii -th day.

Each of the next mm lines contains two integers t_{i},c_{i}ti​,ci​ ( 1<=t_{i}<=2,1<=c_{i}<=10^{6}1<=ti​<=2,1<=ci​<=106 ) — type of the gadget and it's cost. For the gadgets of the first type cost is specified in dollars. For the gadgets of the second type cost is specified in pounds.

输出格式

If Nura can't buy kk gadgets print the only line with the number -1.

Otherwise the first line should contain integer dd — the minimum day index, when Nura will have kk gadgets. On each of the next kk lines print two integers q_{i},d_{i}qi​,di​ — the number of gadget and the day gadget should be bought. All values q_{i}qi​ should be different, but the values d_{i}di​ can coincide (so Nura can buy several gadgets at one day). The days are numbered from 11 to nn .

In case there are multiple possible solutions, print any of them.

输入输出样例

输入 #1复制

5 4 2 2
1 2 3 2 1
3 2 1 2 3
1 1
2 1
1 2
2 2

输出 #1复制

3
1 1
2 3

输入 #2复制

4 3 2 200
69 70 71 72
104 105 106 107
1 1
2 2
1 2

输出 #2复制

-1

输入 #3复制

4 3 1 1000000000
900000 910000 940000 990000
990000 999000 999900 999990
1 87654
2 76543
1 65432

输出 #3

-1

思路

题目大意:

 给定 n 天的美元汇率(a[1]~a[n]),英镑汇率(b[1]~b[n]);m种物品包括,物品类型(type[1]~type[m]) 物品花费(c[1]~c[m]),k 代表需要买多少个物品,s 代表原来拥有的卢布总数。

求解能买到k件物品的最小天数。

注意:一天可以买多个物品,但是一个物品只能买一次;货币可以在任意一天兑换成任意数目的美元或者英镑。

1.假设今天是第3天,那么我可以在第1天,第2天,第3天选择汇率最小的那一天用同样多的卢布换取最大的美元或者英镑数目;

2.1天可以买多个物品,但是1个物品只能买1次;

3.目的是求最小天数,就是找在尽量靠前的天数里面 最小美元汇率 与 最小英镑汇率,能否满足买到k件物品;

4.第i天如果能够买到k件物品,那么尝试再往前一天能否买到,使天数尽量小;如果不能够买到,就向后寻找;如果所有的天数都不满足,那么输出-1。
 

#include <stdio.h>
#include <iostream>
#include <algorithm>
#define maxn 200001
#define ll long long int
#define inf 1000000007
using namespace std;
ll a[maxn],b[maxn],type[maxn],need[maxn],n,m,s,k,cnt,f;
ll pounda[maxn],dollarb[maxn],poundid[maxn],dollarid[maxn],id[maxn];
struct object//物品 
{
	ll id,cost;//id是用什么东西结账,cost是花费 
}obj[maxn];
inline ll cmp(object a,object b)
{
	return a.cost<b.cost;//从小到大 
}
inline ll check(ll i)
{
	register ll ans(0),j;
	for(j=1;j<=m;j++)
	{
		if(type[j]==1)
		{
			obj[j].cost=need[j]*pounda[i];
		}
		else
		{
			obj[j].cost=need[j]*dollarb[i];
		}
		obj[j].id=j;
	}
	sort(obj+1,obj+m+1,cmp);//排序选择最小花费的k个 
	for(j=1;j<=k;j++)
	{
		ans+=obj[j].cost;//累加和 
	}
	return ans;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	register int i,j;
	cin>>n>>m>>k>>s;
	pounda[0]=dollarb[0]=inf;
	for(i=1;i<=n;i++)
	{
		cin>>a[i];
		if(a[i]<pounda[i-1])
		{
			pounda[i]=a[i];//兑换英镑最小汇率 
			poundid[i]=i;//最小汇率的天数 
		}
		else
		{
			pounda[i]=pounda[i-1];
			poundid[i]=poundid[i-1];//连续 
		}
	}
	for(i=1;i<=n;i++)
	{
		cin>>b[i];
		if(b[i]<dollarb[i-1])//同理,兑换美元的最小值和天数 
		{
			dollarb[i]=b[i];
			dollarid[i]=i;
		}
		else
		{
			dollarb[i]=dollarb[i-1];
			dollarid[i]=dollarid[i-1];
		}
	}
	
	for(i=1;i<=m;i++)
	{
		cin>>type[i]>>need[i];//类型和需要钱数 
	}
	f=-1;
	ll l(0),r(n),mid;
	while(l<=r)
	{
		mid=(l+r)>>1;
		if(check(mid)<=s)
		{
			r=mid-1;
			f=mid;
			for(i=1;i<=k;i++)
			{
				id[i]=obj[i].id;
			}
		}
		else
		{
			l=mid+1;
		}
	}
	if(f==-1)
	{
		cout<<f<<endl;
		return 0;
	}
	cout<<f<<endl;
	for(i=1;i<=k;i++)
	{
		if(type[id[i]]==1)
		{
			cout<<id[i]<<' '<<poundid[f]<<endl;;
		}
		else
		{
			cout<<id[i]<<' '<<dollarid[f]<<endl;
		}
	}
	return 0; 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值