C - Coins
Time limit : 2sec / Memory limit : 256MB
Score : 800 points
Problem Statement
There are X+Y+Z people, conveniently numbered 1 through X+Y+Z. Person i has Ai gold coins, Bi silver coins and Ci bronze coins.
Snuke is thinking of getting gold coins from X of those people, silver coins from Y of the people and bronze coins from Z of the people. It is not possible to get two or more different colors of coins from a single person. On the other hand, a person will give all of his/her coins of the color specified by Snuke.
Snuke would like to maximize the total number of coins of all colors he gets. Find the maximum possible number of coins.
Constraints
- 1≤X
- 1≤Y
- 1≤Z
- X+Y+Z≤105
- 1≤Ai≤109
- 1≤Bi≤109
- 1≤Ci≤109
Input
Input is given from Standard Input in the following format:
X Y Z A1 B1 C1 A2 B2 C2 : AX+Y+Z BX+Y+Z CX+Y+Z
Output
Print the maximum possible total number of coins of all colors he gets.
Sample Input 1
1 2 1 2 4 4 3 2 1 7 6 7 5 2 3
Sample Output 1
18
Get silver coins from Person 1, silver coins from Person 2, bronze coins from Person 3 and gold coins from Person 4. In this case, the total number of coins will be 4+2+7+5=18. It is not possible to get 19 or more coins, and the answer is therefore 18.
Sample Input 2
3 3 2 16 17 1 2 7 5 2 16 12 17 7 7 13 2 10 12 18 3 16 15 19 5 6 2
Sample Output 2
110
Sample Input 3
6 2 4 33189 87907 277349742 71616 46764 575306520 8801 53151 327161251 58589 4337 796697686 66854 17565 289910583 50598 35195 478112689 13919 88414 103962455 7953 69657 699253752 44255 98144 468443709 2332 42580 752437097 39752 19060 845062869 60126 74101 382963164
Sample Output 3
3093929975
思路:假设两个人A和B,A(a, b, c)和B(d,e,f),如果选择拿走A的a和B的e,什么情况下拿走A的b和B的d更优呢?自然是a+e<b+d,即a-b<d-e,那么一个贪心策略就出来的,拿走金牌的人的的S金-S银一定大于等于拿走银牌的S金-S银,否则交换这两个人就有更优解。于是对S金-S银作降序排序,拿金的一定在前面,拿银的一定在后面,拿铜的插在中间任何地方,这里用优先队列处理,枚举每一个分界点(金全在左,银全在右)左边和右边能获得最大值即可。(枚举分界点时 金和铜,银和铜同样用上述贪心处理)。
失误处:想到按照金-银排序后,想不到如何处理铜牌,事实上只要限定好条件,确定金和银的分界点就能算出最优解了,还要更熟练使用优先队列。
# include <iostream>
# include <cstdio>
# include <algorithm>
# include <queue>
using namespace std;
typedef long long LL;
const int maxn = 3e5+80;
const LL INF = 0x3f3f3f3f3f3f3f3f;
struct node
{
LL x, y, z;
}a[maxn];
bool cmp1(node na, node nb){return na.x-na.y > nb.x - nb.y;}
struct cmp2 {bool operator ()(node na, node nb) {return na.x-na.z>nb.x-nb.z;}};
struct cmp3 {bool operator ()(node na, node nb) {return na.y-na.z>nb.y-nb.z;}};
priority_queue<node, vector<node>, cmp2>p;
priority_queue<node, vector<node>, cmp3>q;
LL l[maxn], r[maxn];
int main()
{
int x, y, z;
scanf("%d%d%d",&x,&y,&z);
for(int i=1; i<=x+y+z; ++i) scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].z);
sort(a+1, a+1+x+y+z, cmp1);
while(!q.empty()) q.pop();
while(!p.empty()) p.pop();
LL sum = 0;
for(int i=1; i<=x; ++i)
{
sum += (LL)a[i].x;
p.push(a[i]);
}
l[x] = sum;
for(int i=x+1; i<=x+z; ++i)
{
if(p.empty() || a[i].x - a[i].z < p.top().x - p.top().z)
sum += a[i].z;
else
{
sum = sum - p.top().x + p.top().z + a[i].x;
p.pop();
p.push(a[i]);
}
l[i] = sum;
}
sum = 0;
for(int i=x+y+z; i>x+z; --i)
{
q.push(a[i]);
sum += (LL)a[i].y;
}
r[x+z] = sum;
for(int i=x+z; i>x; --i)
{
if(q.empty() || a[i].y - a[i].z < q.top().y - q.top().z)
sum += a[i].z;
else
{
sum = sum - q.top().y + q.top().z + a[i].y;
q.pop();
q.push(a[i]);
}
r[i-1] = sum;
}
LL ans = 0;
for(int i=x; i<=x+z; ++i) ans = max(ans, l[i]+r[i]);
printf("%lld\n",ans);
return 0;
}