LOJ#2306 蔬菜

補充一個題意不太清楚的地方:蔬菜壞掉是假設蔬菜都有標號,那麼特定標號的蔬菜就會在特定時間壞掉。若是你及時賣了它們,那麼那一天就不會有新的蔬菜壞掉。c++

結論1:若是咱們知道了k天的答案,那麼咱們直接扔掉若干個最小的蔬菜便可得到k - 1天的答案。算法

證:由於能在k天賣的必定能在k - 1天賣.....ide

推論1:只要求100000天賣哪些蔬菜便可。spa

結論2:最貴的菜越晚賣越好。rest

證:由於它最貴,因此是必定要賣的。咱們要讓別的菜儘可能賣的多,晚賣有決策包容性。code

推論2:按照從貴到廉考慮蔬菜,每一個菜越晚賣越好。blog

結論3:能夠把每一個蔬菜按照變質天數分類,當天變質的蔬菜可以出售的時間是第一天到當天。get

推論3:假如把每種菜按照變質天數分類,那麼有額外獎勵的蔬菜應該在最後一天。it

證:由於額外獎勵比正常蔬菜貴,因此必定會優先賣它。由結論2可知應放在最後。io

而後算法就出來了。分類以後按順序放蔬菜。天天維護從它開始向前,第一個空閒的地方。能夠用並查集實現。

天天能放多少菜要特別注意,代碼實現上我用總數 - 以前應該留下的菜數來限制。

 

  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\n", ans[t]);
136     }
137 
138     return 0;
139 }
AC代碼
相關文章
相關標籤/搜索