原题地址:http://codeforces.com/contest/867/problem/C
题意:有两种披萨,给你n个人和他们要吃多少片披萨,和他们分别吃到两种披萨的满足度,在给你一个披萨有s片,让你求:
前提是买最少的披萨,可以获得的最大满足度。
思路:首先假设没有最小披萨的限制,那么最优解就是每一个人吃1号披萨和2号披萨中取一个较大的值乘上他所要吃的披萨数.但是现在由于有了最小披萨的限制,我们分别一个人更喜欢吃1号披萨还是2号披萨的数量len1和len2,最后如果len1%s+len2%s是大于一个披萨的话,结果就是不受影响的.但是如果少于s,那就说明肯定有一些更喜欢1号的披萨的人要吃2号披萨,或者喜欢2号披萨的人要去吃1号披萨.因此,对于这种情况,分别比较取一个减少小的就行了.开一个结构体记录去吃不喜欢的披萨所要减少的高兴值.
#include <bits/stdc++.h>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <set>
#include <map>
#include <cctype>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 998244353;
int n, s;
struct node {
ll num, cha;
bool operator <(const node &a)const {
return cha < a.cha;
}
};
vector<node>a, b;
int main() {
scanf("%d%d", &n, &s);
ll numa = 0, numb = 0;
ll ans = 0;
for (int i = 1; i <= n; i++) {
ll s, x, y;
scanf("%I64d%I64d%I64d", &s, &x, &y);
if (x >= y) {
node p;
p.num = s;
p.cha = x - y;
numa += s;
ans += s * x;
a.push_back(p);
} else {
node p;
p.cha = y - x;
p.num = s;
numb += s;
ans +=s * y;
b.push_back(p);
}
}
numa %= s;
numb %= s;
if (numa + numb > s) printf("%I64d\n", ans);
else {
ll sum1 = 0;
sort(a.begin(), a.end());
sort(b.begin(), b.end());
for (int i = 0; i < a.size(); i++) {//分别考虑a,b
if (numa == 0) break;
if (a[i].num <= numa) {
numa -= a[i].num;
sum1 += a[i].num * a[i].cha;
} else {
sum1 += numa * a[i].cha;
numa = 0;
}
}
ll sum2 = 0;
for (int i = 0; i < b.size(); i++) {
if (numb == 0) break;
if (b[i].num <= numb) {
numb -= b[i].num;
sum2 += b[i].num * b[i].cha;
} else {
sum2 += numb * b[i].cha;
numb = 0;
}
}
printf("%I64d\n", ans - min(sum1, sum2));//取一个小值
}
return 0;
}