• Codeforces Round #560 (Div. 3) Microtransactions


    Codeforces Round #560 (Div. 3)

    F2. Microtransactions (hard version)

    题意:

    现在有一个人他每天早上获得1块钱,现在有(n)种商品,每种商品最后需要(k_i)个;现在有(m)个打折信息,每个打折信息包含(d_i,t_i),表示第(t_i)种商品在第(d_i)天打折。如果没有打折的话一个商品卖两块钱,否则卖一块钱。
    现在他可以在任意一天买任意多个商品,当然钱要够用,问最少需要多少天才能把所有需要的商品买完。

    题解:

    其实感觉这个没有多难,二分+贪心就好了。
    因为可以在任意一天买任意多个商品,那么我们只需要在每个商品打折的最后一天买就行了,这肯定是最优的。
    但怎么确定这里的最后一天,二分一下就行了。答案是满足单调性质的。

    代码如下:

    #include <bits/stdc++.h>
    #define MP make_pair
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int N = 4e5 + 5;
    int n, m;
    int last[N];
    vector <pii> v;
    vector <int> Need, days[N];
    bool check(int x) {
        memset(last, 0, sizeof(last)) ;
        for(int i = 0; i < m; i++) {
            pii now = v[i] ;
            if(now.first <= x) last[now.second] = max(last[now.second], now.first) ;
        }
        for(int i = 0; i <= x; i++) days[i].clear() ;
        vector <int> k = Need;
        for(int i = 1; i <= n; i++)
            if(last[i] != 0) days[last[i]].push_back(i) ;
        int money = 0;
        for(int i = 1; i <= x; i++) {
            money++;
            if(i > 200000) {
                money += x - i;
                break ;
            }
            for(auto p : days[i]) {
                if(money >= k[p]) {
                    money -= k[p] ;
                    k[p] = 0;
                } else {
                    k[p] -= money ;
                    money = 0;
                    break ;
                }
            }
        }
        return accumulate(k.begin(), k.end(), 0) * 2 <= money ;
    }
    int main() {
        ios::sync_with_stdio(false); cin.tie(0) ;
        cin >> n >> m;
        Need.push_back(0) ;
        for(int i = 1; i <= n; i++){
            int tmp;
            cin >> tmp;
            Need.push_back(tmp) ;
        }
        for(int i = 0; i < m; i++) {
            int d, t;
            cin >> d >> t;
            v.push_back(MP(d, t)) ;
        }
        int l = 1, r = 400001, mid ;
        while(l < r) {
            mid = (l + r) >> 1;
            if(check(mid)) r = mid ;
            else l = mid + 1;
        }
        cout << l;
        return 0;
    }
    
  • 相关阅读:
    解决 Cordova 打包 vue项目为 APP 后,在安卓平台下 touchMove 事件不生效的问题
    解决微信内置浏览器里,下拉无法捕获 touchEnd 事件
    记录 React-native 项目中的各种坑坑
    内存型游戏外挂讲解
    浅谈数据抓取的几种方法
    php链表笔记:合并两个有序链表
    php链表笔记:链表的检测
    php链表笔记:单链表反转
    使用UUID和int自增主键的区别
    lumen框架使用Elasticsearch详解
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/10877494.html
Copyright © 2020-2023  润新知