• LOJ#2306 蔬菜


    补充一个题意不太清楚的地方:蔬菜坏掉是假设蔬菜都有标号,那么特定标号的蔬菜就会在特定时间坏掉。如果你及时卖了它们,那么那一天就不会有新的蔬菜坏掉。

    结论1:如果我们知道了k天的答案,那么我们直接扔掉若干个最小的蔬菜即可获得k - 1天的答案。

    证:因为能在k天卖的一定能在k - 1天卖.....

    推论1:只要求100000天卖哪些蔬菜即可。

    结论2:最贵的菜越晚卖越好。

    证:因为它最贵,所以是一定要卖的。我们要让别的菜尽量卖的多,晚卖有决策包容性。

    推论2:按照从贵到廉考虑蔬菜,每个菜越晚卖越好。

    结论3:可以把每个蔬菜按照变质天数分类,当天变质的蔬菜能够出售的时间是第一天到当天。

    推论3:假如把每种菜按照变质天数分类,那么有额外奖励的蔬菜应该在最后一天。

    证:因为额外奖励比正常蔬菜贵,所以一定会优先卖它。由结论2可知应放在最后。

    然后算法就出来了。分类之后按顺序放蔬菜。每天维护从它开始向前,第一个空闲的地方。可以用并查集实现。

    每天能放多少菜要特别注意,代码实现上我用总数 - 之前应该留下的菜数来限制。

      1 #include <bits/stdc++.h>
      2 
      3 inline char gc() {
      4     /*static char buf[1000000], *p1, *p2;
      5     if(p1 == p2) p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin);
      6     return (p1 == p2) ? EOF : *p1++;*/ return getchar();
      7 }
      8 
      9 template <class T> inline void read(T &x) {
     10     x = 0;
     11     char c = gc();
     12     bool f = 0;
     13     while(c < '0' || c > '9') {
     14         if(c == '-') f = 1;
     15         c = gc();
     16     }
     17     while(c >= '0' && c <= '9') {
     18         x = x * 10 + c - 48;
     19         c = gc();
     20     }
     21     if(f) x = (~x) + 1;
     22     return;
     23 }
     24 
     25 typedef long long LL;
     26 const int N = 100010;
     27 
     28 struct Node {
     29     int val, d, id, cnt, flag;
     30     Node(int V = 0, int D = 0, int ID = 0, int C = 0, int F = 0) {
     31         val = V;
     32         d = D;
     33         id = ID;
     34         cnt = C;
     35         flag = F;
     36     }
     37     inline bool operator <(const Node &w) const {
     38         if(val != w.val)
     39             return val < w.val;
     40         return d < w.d;
     41     }
     42 };
     43 
     44 std::priority_queue<Node> Q, Q2;
     45 int a[N], s[N], c[N], x[N], fa[N], rest[N];
     46 LL ans[N];
     47 
     48 int find(int x) {
     49     if(x == fa[x]) return x;
     50     return fa[x] = find(fa[x]);
     51 }
     52 
     53 inline void del(LL &a) {
     54     Node t = Q2.top();
     55     Q2.pop();
     56     a += t.val;
     57     t.cnt--;
     58     if(t.cnt) Q2.push(t);
     59     return;
     60 }
     61 
     62 int main() {
     63 
     64     int n, m, k, lm = 100000;
     65     read(n); read(m); read(k);
     66     for(int i = 1; i <= lm; i++) {
     67         fa[i] = i;
     68         rest[i] = m;
     69     }
     70     for(int i = 1; i <= n; i++) {
     71         read(a[i]); read(s[i]); read(c[i]); read(x[i]);
     72         LL day;
     73         if(!x[i]) {
     74             day = lm;
     75         }
     76         else {
     77             day = std::min((c[i] - 1) / x[i] + 1, lm);
     78         }
     79         Q.push(Node(a[i] + s[i], day, i, 1, 0));
     80         if((day - 1) * x[i] + 1 < c[i]) { /// the last day have rest
     81             Q.push(Node(a[i], day, i, c[i] - 1 - x[i] * (day - 1), 0));
     82         }
     83         if(day > 1 && x[i]) {
     84             Q.push(Node(a[i], day - 1, i, x[i] * (day - 1), 1));
     85         }
     86         //c[i]--;
     87     }
     88 
     89     //int Last = 0, Cnt = 0;
     90 
     91     int tot = 0;
     92     while(Q.size()) {
     93         Node t = Q.top();
     94         Q.pop();
     95         int now = find(t.d);
     96         while(now && t.cnt) {
     97             LL large;
     98             if(t.flag) large = std::min(t.cnt, std::min(t.cnt - x[t.id] * (now - 1), rest[now]));
     99             else if(x[t.id]) large = std::min(t.cnt, std::min(x[t.id], rest[now]));
    100             else large = std::min(t.cnt, rest[now]);
    101 
    102             ans[lm] += t.val * large;
    103             tot += large;
    104             Q2.push(Node(-t.val, 0, t.id, large));
    105             rest[now] -= large;
    106             t.cnt -= large;
    107             if(!rest[now]) {
    108                 fa[now] = find(now - 1);
    109             }
    110             now = find(now - 1);
    111         }
    112     }
    113 
    114 
    115     int day = (tot - 1) / m + 1; /// need (day) to sell the vegetables
    116 
    117     for(int i = lm - 1; i >= day; i--) {
    118         ans[i] = ans[lm];
    119     }
    120     ans[day - 1] = ans[day];
    121     for(int T = 1; T <= tot - m * (day - 1); T++) {
    122         del(ans[day - 1]);
    123     }
    124 
    125     for(int i = day - 2; i >= 1; i--) {
    126         ans[i] = ans[i + 1];
    127         for(int T = 1; T <= m; T++) {
    128             del(ans[i]);
    129         }
    130     }
    131 
    132     for(int i = 1; i <= k; i++) {
    133         int t;
    134         read(t);
    135         printf("%lld
    ", ans[t]);
    136     }
    137 
    138     return 0;
    139 }
    AC代码
  • 相关阅读:
    网络编程【二】socket(套接字)初识
    网络编程【一】操作系统的发展史
    面向对象【十三】类的魔术方法
    面向对象【十二】包装和授权
    面向对象【十一】类内置的attr属性
    面向对象【十】反射
    openwrt 编译错误
    修改openwrt 终端登录欢迎界面
    openwrt quilt 使用
    openwrt luci 入门介绍
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10580278.html
Copyright © 2020-2023  润新知