题目链接
还是可以的一道题,但是多次写飙……也是醉了,题意就是给你N天,每天都有一个相对应的美元以及英镑的汇率,就是每单位钱需要多少卢比。然后,还有M个物品,他们有相应的价值:第一个数表示,它支持美元支付还是英镑支付——“1”代表美元、“2”代表英镑,然后是所需的对应货币的数量。我们要K个这样的物品,并且,我们有S个卢比(初始的时候),然后,我们可以用卢比去换钱,问:最早第几天的时候,我们可以拿齐K中物品。
那么,我们可以二分答案,去假设第几天的时候会拿到K个物品,然后处理一下前缀最小值的货币汇率,因为我们可以最后一天再买所有的物品,之前只用囤钱就行了,所以,每个物品的哪天买的时间,可以都为期限时间(SPJ)。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include<time.h>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define efs 1e-7
#define son1 (j-1)>0? ans[i-1][j-1] : 0
#define son2 (j+1)<=M? ans[i-1][j+1] : 0
#define son3 (i-2)>0? ans[i-2][j] : 0
#define copppy(pr, ans) memcpy(pr, ans, sizeof(ans))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, M, K, need_D, need_P; //Amer、US分别记录美元、英镑的前缀最小值,就是可以换钱的最小值,need_D和need_P分别记录需要美元和英镑的物品的数量
ll Amer[maxN], US[maxN], S;
pair<ll, int> vD[maxN], vP[maxN];
int day_D[maxN], day_P[maxN]; //改天对应的最优货币解
int used_D, used_P, ans_D, ans_P;
void init()
{
Amer[0] = US[0] = Amer[N+1] = US[N+1] = INF;
need_D = need_P = ans_D = ans_P = 0;
}
bool solve(int day)
{
ll sum = 0;
ll dollar = Amer[day], pound = US[day];
int kk = min(K, need_D); //用kk记录下使用美元的最大数量
used_D = kk;
for(int i=1; i<=kk; i++)
{
sum += dollar * vD[i].first;
}
int tot = K - kk;
used_P = tot;
for(int i=1; i<=tot; i++)
{
sum += pound * vP[i].first;
}
int pp = min(K, need_P);
for(int i=tot+1; i<=pp; i++)
{
if(sum <= S) { ans_D = used_D; ans_P = used_P; return true; }
if(kk == 0) break;
sum += pound * vP[i].first;
sum -= dollar * vD[kk--].first;
used_P++;
used_D--;
}
if(sum <= S) { ans_D = used_D; ans_P = used_P; return true; }
return false;
}
void Print(int day)
{
if(day <= 0) return;
for(int i=1; i<=ans_D; i++) printf("%d %d\n", vD[i].second, day_D[day]);
for(int i=1; i<=ans_P; i++) printf("%d %d\n", vP[i].second, day_P[day]);
}
int main()
{
while(scanf("%d%d%d%lld", &N, &M, &K, &S)!=EOF)
{
init();
for(int i=1; i<=N; i++)
{
ll e1; scanf("%lld", &e1);
if(e1 < Amer[i-1])
{
day_D[i] = i;
Amer[i] = e1;
}
else
{
day_D[i] = day_D[i-1];
Amer[i] = Amer[i-1];
}
}
for(int i=1; i<=N; i++)
{
ll e1; scanf("%lld", &e1);
if(e1 < US[i-1])
{
day_P[i] = i;
US[i] = e1;
}
else
{
day_P[i] = day_P[i-1];
US[i] = US[i-1];
}
}
for(int i=1; i<=M; i++)
{
int op; scanf("%d", &op);
if(op == 1)
{
scanf("%lld", &vD[++need_D].first);
vD[need_D].second = i;
}
else
{
scanf("%lld", &vP[++need_P].first);
vP[need_P].second = i;
}
}
sort(vD + 1, vD + 1 + need_D);
sort(vP + 1, vP + 1 + need_P);
int L = 1, R = N, ans = -1, mid = 0;
while(L <= R)
{
mid = (L + R)/2;
if(solve(mid)) { R = mid - 1; ans = mid; }
else L = mid + 1;
}
if(ans == 0) ans = -1;
printf("%d\n", ans);
Print(ans);
}
return 0;
}
/*
10 10 10 1000000
836 842 645 671 499 554 462 288 89 104
880 722 623 651 591 573 154 532 136 59
1 47
1 169
2 486
1 262
2 752
2 498
2 863
2 616
1 791
1 656
Answer:
9
1 9
2 9
4 9
10 9
9 9
3 9
6 9
8 9
5 9
7 9
*/