AGC 018 C Coin (堆)

来源:互联网 发布:运营商的云计算项目 编辑:程序博客网 时间:2024/06/10 00:16

Description

X+Y+Z个人,每个人有一定的金、银、铜币,你可以向X个人要金币,向Y个人要银币,向Z个人要铜币,且不能向同一个人要两种不同的钱币,问能拿到的钱币数量的最大值。

Solution

按金币减去银币的数量从小到大排序:
在这个顺序下,最佳方案中所有给予金币的人都在给予银币的人的右边。(想一想,为什么)
存在整数K使得:左边的K个人中,有Y个给银币的人,(K-Y)个给铜币的人;其余的人中有X个给金币的人和(Y+Z-K)个给铜币的人。
我们假设每个人都没有铜币,使金币、银币的数量都减去铜币的数量,并在最终的答案中加上铜币数量。
然后我们就可以求出左边K个人的银币中最大的Y个,其余右边的人的金币中最大的X个,用堆维护即可。

Code

我已经成为缩行大师了?

//Author: Hany01//Copyright 2017 (C) Hany01#include<bits/stdc++.h>#define For(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i <= i##_end_ ; ++ i)#define Fordown(i , j , k) for (register int i = (j) , i##_end_ = (k) ; i >= i##_end_ ; -- i)using namespace std;typedef long long LL;template <typename T> inline bool chkmax(T &a , T b) { return a < b ? (a = b , 1) : 0; }int _ , __; char c_;inline int read() {    for (_ = 0 , __ = 1 , c_ = getchar() ; !isdigit(c_) ; c_ = getchar()) if (c_ == '-') __ = -1;    for ( ; isdigit(c_) ; c_ = getchar()) _ = (_ << 1) + (_ << 3) + (c_ ^ 48); return _ * __;}const int maxn = 100010;struct Item{    int x , y , z;    bool operator < (const Item &item) const { return x - y > item.x - item.y; }}a[maxn];int X, Y, Z, n, q[maxn], cnt;LL Ans, Sumy, Sumz, pre[maxn];inline void Init(){    X = read(); Y = read(); Z = read(); n = X + Y + Z;    For(i, 1, n) a[i].x = read(), a[i].y = read(), a[i].z = read();    sort(a + 1 , a + 1 + n);    For(i, 1, n) a[i].x -= a[i].z, a[i].y -= a[i].z, Sumz += a[i].z;}inline void Solve(){    For(i, 1, X) q[cnt ++] = -a[i].x, pre[X] += a[i].x;    make_heap(q , q + cnt);    For(i, X + 1, n - Y) q[cnt ++] = -a[i].x, push_heap(q, q + cnt), pre[i] = (pre[i - 1] + a[i].x + q[0]), pop_heap(q, q + (cnt --));    cnt = 0; For(i, n - Y + 1, n) q[cnt ++] = -a[i].y, Sumy += a[i].y;    make_heap(q, q + cnt);    Ans = Sumy + pre[n - Y];    Fordown(i, n - Y, X + 1)        q[cnt ++] = -a[i].y, push_heap(q, q + cnt), Sumy += a[i].y + q[0], chkmax(Ans, Sumy + pre[i - 1]), pop_heap(q, q + (cnt --));    printf("%lld\n" , Ans + Sumz);}int main(){    Init();    Solve();    return 0;}