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