Gadgets for dollars and pounds【CodeForces 609D】【二分答案+貪心】
阿新 • • 發佈:2018-12-25
題目連結
還是可以的一道題,但是多次寫飆……也是醉了,題意就是給你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 */