标签:return 注意 queue iostream open clu cto scan max
这个是最难的,一个贪心,很经典,但是我不会,早训结束看了题解才知道怎么贪心的。
这个是先假设每个人都可以吃到他喜欢的,就是先求出答案,然后按照b-a 排序,分别放入两个优先队列里面,
如果b>a 那就吃第二块,否则就吃第一块,求出num,注意优先队列按照从小到达排序。
num1记录第一块吃的数量,num2记录第二块吃的数量。
num1%=s,num2%=s 如果num1+num2的数量大于等于了s 则说明可以满足。
如果小于s了,说明他们只能选一块吃,这个时候在求出答案后贪心,贪心取最少的代价使得只吃一块。
两边都利用优先队列进行贪心。
很好的一个题目。
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <vector> #include <iostream> #include <string> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 1e5 + 10; typedef long long ll; struct node { int num, happy; node(int num = 0, int happy = 0) :num(num), happy(happy) {} bool operator< (const node &a)const { return a.happy < happy; } }; priority_queue<node>v1, v2; int a[maxn], b[maxn]; int main() { ll n, s; scanf("%lld%lld", &n, &s); ll num1 = 0, num2 = 0, ans = 0; for(int i=1;i<=n;i++) { int num; scanf("%d%d%d", &num, &a[i], &b[i]); if (a[i] > b[i]) num1 += num, v1.push(node(num, a[i]-b[i])); else num2 += num, v2.push(node(num, b[i]-a[i])); ans += num * 1ll * max(a[i], b[i]); } num1 %= s, num2 %= s; if (num1 + num2 > s) printf("%lld\n", ans); else { // printf("num1=%lld num2=%lld ans=%lld\n", num1, num2, ans); ll res1 = 0, cost1 = 0, res2 = 0, cost2 = 0; while(!v1.empty()) { node u = v1.top(); v1.pop(); int num = u.num; if(res1+num>=num1) { cost1 += (num1 - res1)*u.happy; break; } res1 += num; cost1 += num * u.happy; } while(!v2.empty()) { node u = v2.top(); v2.pop(); int num = u.num; if(res2+num>=num2) { cost2 += (num2 - res2)*u.happy; break; } res2 += num; cost2 += num * u.happy; // printf("cost2=") } // printf("cost2=%lld\n", cost2); ans = max(ans - cost1, ans - cost2); printf("%lld\n", ans); } return 0; }
C - Ordering Pizza CodeForces - 867C 贪心 经典
标签:return 注意 queue iostream open clu cto scan max
原文地址:https://www.cnblogs.com/EchoZQN/p/11404112.html