前言

每次期末后的复建运动都格外痛苦(

正文

题意是说,给定\(n\)本书,如果书都有属性\(a,b,t\)。如果\(a=1\),则说明Alice喜欢读这本书,\(0\)则不喜欢;如果\(b=1\),则说明Bob喜欢读这本书,\(0\)则不喜欢。\(t\)是每本书的代价。从中选出若干本书,这些书中Alice和Bob喜欢读的都不少于\(k\)本。问如何选择,才能使代价总和最小。

思路是贪心。记Alice和Bob都喜欢的书为11类,只有Alice喜欢的为10类,只有Bob喜欢的为01类。容易注意到,选择Alice和Bob都喜欢读的书性价比要更高一些。所以,我们首先对三种属性分别排序,如果当前取了\(i\)本11类的书,那么,对于Alice,我们要为她取10类和01类共\(k-i\)本书;Bob也是同理。如果发现10类或01类的书的数目小于\(k-i\),则说明在取\(i\)本11类书的情况下,没有可行的方案。

代码如下:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <vector>
#define mst(a, b) memset((a), (b), sizeof(a))
#define debug printf("debug\n")
#define INF 0x3f3f3f3f
#define lson lef, mid, rt << 1
#define rson mid + 1, rig, rt << 1 | 1
const int maxn = 2e5 + 5;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
struct node {
    ll t;
    int a;
    int b;
    bool operator<(const node& nn) const
    {
        return t < nn.t;
    }
};
node allone[maxn];
node A[maxn];
node B[maxn];
ll sum1[maxn];
ll sum2[maxn];
ll sum3[maxn];
unordered_map<int, bool> mp;
int main()
{
    mp.clear();
    int n, k;
    scanf("%d %d", &n, &k);
    int idx1, idx2, idx3;
    idx1 = idx2 = idx3 = 1;
    ll t_;
    int a_, b_;
    for (int i = 1; i <= n; i++) {
        scanf("%lld %d %d", &t_, &a_, &b_);
        if (a_ && b_)
            allone[idx1++] = { t_, a_, b_ };
        if (a_ && !b_)
            A[idx2++] = { t_, a_, b_ };
        if (!a_ && b_)
            B[idx3++] = { t_, a_, b_ };
    }
    sort(allone + 1, allone + idx1);
    sort(A + 1, A + idx2);
    sort(B + 1, B + idx3);
    for (int i = 1; i <= n; i++) {
        sum1[i] = sum1[i - 1] + allone[i].t;
        sum2[i] = sum2[i - 1] + A[i].t;
        sum3[i] = sum3[i - 1] + B[i].t;
    }
    ll inf = numeric_limits<ll>::max();
    ll ans = inf;
    for (int i = 0; i <= min(k, idx1 - 1); i++) {
        int tmp = k - i;
        if (idx2 - 1 >= tmp && idx3 - 1 >= tmp) {
            ans = min(ans, sum1[i] + sum2[k - i] + sum3[k - i]);
        }
    }
    if (ans == inf) {
        puts("-1");
    } else {
        printf("%lld\n", ans);
    }
    return 0;
}