zoukankan      html  css  js  c++  java
  • [NOI 2017]蔬菜

    Description

    题库链接

    小 N 是蔬菜仓库的管理员,负责设计蔬菜的销售方案。

    在蔬菜仓库中,共存放有 (n) 种蔬菜,小 N 需要根据不同蔬菜的特性,综合考虑各方面因素,设计合理的销售方案,以获得最多的收益。

    在计算销售蔬菜的收益时,每销售一个单位第 (i) 种蔬菜,就可以获得 (a_i) 的收益。

    特别地,由于政策鼓励商家进行多样化销售,第一次销售第 i 种蔬菜时,还会额外得到 (s_i) 的额外收益。

    在经营开始时,第 (i) 种蔬菜的库存为 (c_i) 个单位。

    然而,蔬菜的保鲜时间非常有限,一旦变质就不能进行销售,不过聪明的小 N 已经计算出了每个单位蔬菜变质的时间:对于第 (i) 种蔬菜,存在保鲜值 (x_i) ,每天结束时会有 (x_i) 个单位的蔬菜变质,直到所有蔬菜都变质。(注意:每一单位蔬菜的变质时间是固定的,不随销售发生变化)

    形式化地:对于所有的满足条件 (d imes x_i leqslant ci) 的正整数 (d) ,有 (x_i) 个单位的蔬菜将在第 (d) 天结束时变质。

    特别地,若 ((d - 1) imes x_i leqslant c_i leqslant d imes x_i) ,则有 (c_i - (d - 1) imes x_i) 单位的蔬菜将在第 (d) 天结束时变质。

    注意,当 (x_i = 0) 时,意味着这种蔬菜不会变质。

    同时,每天销售的蔬菜总量也是有限的,最多不能超过 (m) 个单位。

    现在,小 N 有 (k) 个问题,想请你帮忙算一算。每个问题的形式都是:对于已知的 (p_j) ,如果需要销售 (p_j) 天,最多能获得多少收益?

    (1leq n,k,p_ileq 100000,1leq mleq 10,0<a_i,c_ileq 10^9,0leq s_i,x_ileq 10^9)

    Solution

    可以倒着做,从后往前贪。我们先计算 (p=maxp=100000)

    由于有额外收益,我们可以将一个蔬菜分成前 (c_i-1)(a_i) ,最后 (1)(a_i+s_i)

    这样题目模型就从蔬菜坏掉转化为了一个“进货”操作。

    优先队列来解决。

    考虑如何求其余的 (p) 。我们同样倒推。

    因为前 (p) 天推到前 (p-1) 天时第 (p) 天买的一定能够在前 (p-1) 天买。所以同样开一个小根堆,控制堆的大小只有 (mp) 即可。

    Code

    #include <bits/stdc++.h>
    #define pb push_back
    #define ll long long
    using namespace std;
    const int N = 100000+5, MAXP = 100000;
    
    int n, m, k, a[N], s[N], c[N], x[N], used[N], p;
    vector<int> veg[N];
    vector<int>::iterator it;
    struct node {
        int val, id;
        bool operator < (const node &b) const {return val < b.val; }    
    } t;
    priority_queue<node> Q;
    priority_queue<int, vector<int>, greater<int> > PQ;
    queue<int> P;
    ll tol, ans[N];
    
    void work() {
        scanf("%d%d%d", &n, &m, &k);
        for (int i = 1; i <= n; i++) scanf("%d%d%d%d", &a[i], &s[i], &c[i], &x[i]);
        for (int i = 1; i <= n; i++) {
            if (x[i] == 0) veg[MAXP].pb(i);
            else veg[min(MAXP, (c[i]+x[i]-1)/x[i])].pb(i);
        }
        for (int i = MAXP; i >= 1; i--) {
            for (it = veg[i].begin(); it != veg[i].end(); it++)
                Q.push((node){a[*it]+s[*it], *it});
            for (int lim = m; lim && !Q.empty(); --lim, Q.pop()) {
                t = Q.top();
                if (used[t.id] == 0) {
                    tol += t.val; ++used[t.id], PQ.push(t.val);
                    Q.push((node){a[t.id], t.id});
                }else {
                    if (c[t.id]-1ll*x[t.id]*(i-1) > used[t.id]) {
                        tol += t.val; ++used[t.id], PQ.push(t.val);
                        Q.push((node){a[t.id], t.id});
                    }else P.push(t.id), ++lim;
                }
            }
            while (!P.empty()) {
                int u = P.front(); P.pop();
                if (used[u] != c[u]) Q.push((node){a[u], u});
            }
        }
        ans[MAXP] = tol;
        for (int i = MAXP-1; i >= 1; i--) {
            while (PQ.size() > 1ll*i*m) tol -= PQ.top(), PQ.pop();
            ans[i] = tol;
        }
        while (k--) {scanf("%d", &p); printf("%lld
    ", ans[p]); }
    }
    int main() {work(); return 0; }
  • 相关阅读:
    nodejs 文件路径问题
    nodejs
    return , return true , return false的区别
    严防个人极端案事件 中央政法委要求健全危机干预机制
    《资本论》:什么是“原始积累”?农民的土地因何被社会剥夺
    程序员自我修炼(四)—— 代码重构
    中国各民族人口总数排名
    农村人可以去别的村买宅基地吗?这样合不合法?看完你就知道了!
    如果所在的农村拆迁了,可以在另外一个村申请宅基地吗?
    哈姆扎&#183;本&#183;拉登为什么反对美国?
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/9294255.html
Copyright © 2011-2022 走看看