codeforces 609D D. Gadgets for dollars and pounds(二分+贪心)
原创
©著作权归作者所有:来自51CTO博客作者mb5f5b1df7f1e34的原创作品,请联系作者获取转载授权,否则将追究法律责任
Gadgets for dollars and pounds
总时间限制: 2000ms 内存限制: 65536kB
描述
一个人手上有s卢布,他要在n天内买m样东西中的k样.
有两种支付方式,每个物品有一种支付方式,要么用美元,要么用英镑。每天有不同的支付方式代价,即换取一美元或英镑,需要付出x[i]卢布的代价。
要求:最早完成买k样东西的天数。如果无法完成任务,输出-1
一种商品只能购买一次,但是一天可以买多种商品
输入
第1行:n, m, k, s
第2行:n个整数,表示多少卢布换一美元
第3行:n个整数,表示多少卢布换一英镑
接下来是m行,每行2个整数,表示每样东西用什么货币结账(1是美元,2是英镑),以及要多少那种外币
输出
输出最短到第几天买完k样商品 和方案
样例输入
input
Copy
5 4 2 2
1 2 3 2 1
3 2 1 2 3
1 1
2 1
1 2
2 2
output
Copy
3
1 1
2 3
input
Copy
4 3 2 200
69 70 71 72
104 105 106 107
1 1
2 2
1 2
output
Copy
-1
input
Copy
4 3 1 1000000000
900000 910000 940000 990000
990000 999000 999900 999990
1 87654
2 76543
1 65432
output
Copy
-1
提示
【数据规模】
1 ≤ n ≤ 2·10^5 , 1 ≤ k ≤ m ≤ 2·10^5 , 1 ≤ s ≤ 10^9
1 ≤ ai, bi ≤ 10^6
1 ≤ t ≤ 2, 1 ≤ c ≤ 10^6
分析:暴力枚举天数就会超时,首先我们要知道如果第k天能买完东西,那么k-1天肯定也能买完东西,所以它符合一个上升的子序列,所以我们二分枚举答案天数,对于商品的花费,我们可以对齐贪心排序(注意要记录商品序号,因为最后要输出),花费小的在钱买你,然后用两个前缀和来记录前i个商品的最小美元和英镑花费,在二分判断条件时,看他的钱是否足够就行,,输出结果即可。
一份java超时代码,但这个思想C++能过,估计Java的输入输出的原因,回来我改改做做
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
static final long mod=1000000007;
static final int N=1000007;
static day[] d=new day[N];
static ArrayList<goods> listd=new ArrayList<goods>();
static ArrayList<goods> listp=new ArrayList<goods>();
static Long[] sumd=new Long[N];
static Long[] sump=new Long[N];
static int n,m,k;
static long s;
static int dnum;
static int pnum;
static int dday;
static int pday;
public static void main(String args[])throws IOException {
Scanner in = new Scanner(System.in);
n=in.nextInt();m=in.nextInt();k=in.nextInt();
s=in.nextLong();
for(int i=1;i<=n;i++)
{
d[i]=new day();
d[i].a=in.nextInt();
}
for(int i=1;i<=n;i++)
{
d[i].b=in.nextInt();
}
for(int i=1;i<=m;i++)
{
int op=in.nextInt();
Long x=in.nextLong();
if(op==1)
{
listd.add(new goods(x,i));
}
else
listp.add(new goods(x,i));
}
Collections.sort(listd, new Comparator<goods>(){
public int compare(goods a, goods b) {
return (int)(a.cost-b.cost);
}
});
sumd[0]=(long) 0;
sumd[1]=listd.get(0).cost;
for(int i=1;i<listd.size();i++)
{
sumd[i+1]=sumd[i]+listd.get(i).cost;
}
Collections.sort(listd, new Comparator<goods>(){
public int compare(goods a, goods b) {
return (int)(a.cost-b.cost);
}
});
sump[0]=(long) 0;
sump[1]=listp.get(0).cost;
for(int i=1;i<listp.size();i++)
{
sump[i+1]=sump[i]+listp.get(i).cost;
}
int l=1,r=n;
while(l<r)
{
int mid=(l+r)>>1;
//System.out.println(mid);
if(cal(mid)==1)
{
r=mid;
}
else
{
l=mid+1;
}
}
if(l==n)
{
System.out.println(-1);
}
else
{
System.out.println(l);
for(int i=0;i<dnum;i++)
{
System.out.println(listd.get(i).id+" "+dday);
}
for(int i=0;i<pnum;i++)
{
System.out.println(listp.get(i).id+" "+pday);
}
}
}
private static int cal(int mid) {
int min1=(1<<30),min2=(1<<30);
int pd = 0,pp = 0;
for(int i=1;i<=mid;i++)
{
if(min1>d[i].a)
{
min1=d[i].a;
pd=i;
}
if(min2>d[i].b)
{
min2=d[i].b;
pp=i;
}
}
long sum1=0,sum2=0;
for(int i=0;i<=listd.size();i++)
{
int j=k-i;
if(j>listp.size()||j<0) continue;
//System.out.println(min1+" "+min2);
if(sumd[i]*min1+sump[j]*min2<=s)
{
dnum=i;
pnum=j;
dday=pd;
pday=pp;
return 1;
}
}
return 0;
}
}
class goods
{
long cost;
int id;
public goods() {
}
public goods(long cost, int id) {
this.cost = cost;
this.id = id;
}
}
class day
{
public int a,b;
public day(int a, int b) {
this.a = a;
this.b = b;
}
public day() {
// TODO 自动生成的构造函数存根
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}