先全部选 \(a_i\),假设 \(b_i=b_i-a_i,c_i=c_i-a_i\)。
那么题目转化为选 \(y\) 个 \(b\) 和 \(z\) 个 \(c\) 使得答案最大。
会发现若 \(i\) 位置选的 \(b\),\(j\) 位置选的 \(c\),那么需要满足 \(b_i-c_i>b_j-c_j\)。
我们按上述条件排序,这样一定是在左边选 \(b\),右边选 \(c\)。
那么题目又简化为给定数组 \(b\),在前 \(i\) 个里面选出 \(y\) 个数的最大和,直接反悔贪心即可。
//dzzfjldyqqwsxdhrdhcyxll
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 1e5 + 10;
int x,y,z,n,sum,f[MAXN],g[MAXN],ans = -1e18;
struct Node {
int a,b,c;
}q[MAXN];
inline bool cmp(Node x,Node y) {
return x.b - x.c > y.b - y.c;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> x >> y >> z;
n = x + y + z;
for(int i = 1;i <= n;i++) {
cin >> q[i].a >> q[i].b >> q[i].c;
sum += q[i].a;
q[i].b -= q[i].a;
q[i].c -= q[i].a;
}
sort(q + 1,q + n + 1,cmp);
priority_queue <int,vector <int>,greater <int> > Q;
for(int i = 1;i <= n;i++) {
if(Q.size() < y) {
f[i] = f[i - 1] + q[i].b;
Q.push(q[i].b);
} else {
f[i] = f[i - 1];
if(Q.top() < q[i].b) {
f[i] += q[i].b - Q.top();
Q.pop();
Q.push(q[i].b);
}
}
}
while(!Q.empty()) Q.pop();
for(int i = n;i >= 1;i--) {
if(Q.size() < z) {
g[i] = g[i + 1] + q[i].c;
Q.push(q[i].c);
} else {
g[i] = g[i + 1];
if(Q.top() < q[i].c) {
g[i] += q[i].c - Q.top();
Q.pop();
Q.push(q[i].c);
}
}
}
for(int i = y;i <= n - z;i++) {
ans = max(ans,f[i] + g[i + 1]);
}
cout << ans + sum;
return 0;
}
标签:Node,int,题解,Coins,cin,MAXN,AGC018C
From: https://www.cnblogs.com/Creeperl/p/18549433