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;
}
View Code

 

posted @ 2019-06-01 11:14  html_11  阅读(135)  评论(0编辑  收藏  举报