Codeforces Round # 560 (Div. 3) F2. Microtransactions (complicated version) (二分)
题目链接:http://codeforces.com/contest/1165/problem/F2
题意:n种物品需要购买,每种物品需要购买a[i]件,每件物品价格为2bourle,有m次优惠活动(di,ti):第di天物品ti价值优惠为1bourle
每天可以得到1bourle,求买完所有物品的最少天数。
思路:设所有物品数量为cnt,最少天数一定在[cnt,2 * cnt]之间,因为获得的物品数目随天数是递增的,所以二分找最优解
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <map> #include <set> #include <vector> #include <string> #include <cmath> #include <queue> #define rep(i, s, e) for(int i = s; i < e; ++i) #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define P pair<int, int> #define INF 0x3f3f3f3f #define Mod 998244353 using namespace std; typedef long long ll; static const int N = 1005; static const int MAX_N = 2e5 + 5; int a[MAX_N], b[MAX_N]; vector<int>vec[MAX_N << 1]; int n; bool judge(int x, int cnt, vector<int>vec[]){ int day = x; //花费天数(即可花费的bourle,因为每天可获得1bourle) for(int i = 1; i <= n; ++i) b[i] = a[i]; int cur = 0; for(int i = x; i >= 1; --i){ //x天的优惠活动 for(int j = 0; j < vec[i].size(); ++j){ int t = vec[i][j]; while(b[t] && day){ //尽可能多的在优惠中购买物品 --b[t]; --cnt; //物品总数 --day; //bourle数量减少 } } while(day >= i) ++cur, --day; //borcle数目不能超过天数,多余部分只能用于未参与优惠的物品(这里条件控制的比较好,用if也行) } return cur >= 2 * cnt; //未参与优惠的物品需2bourle } void solve(){ // freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); //ios::sync_with_stdio(false); int m; while(scanf("%d%d", &n, &m) != EOF){ int cnt = 0; for(int i = 0; i < (MAX_N << 1); ++i) vec[i].clear(); for(int i = 1; i <= n; ++i){ scanf("%d", &a[i]); cnt += a[i]; } for(int i = 0; i < m; ++i){ int u, v; scanf("%d%d", &u, &v); vec[u].push_back(v); } int l = cnt, r = cnt << 1; int ans = 0; while(l <= r){ int m = l + r >> 1; if(judge(m, cnt, vec)){ r = m - 1; ans = m; } else l = m + 1; } printf("%d\n", ans); } } int main() { solve(); return 0; }