CF332C Students' Revenge

洛谷

CF

分析

假设我们选出了 \(p\) 个任务,那么主席一定会将其按照: \(x.b>y.b\)\(x.a<y.a\) 的排序方式将其排序,然后选择前 \(k\) 个任务完成。所以我们先按照这种方式排序,后 \(p-k\) 个是一定不会被主席选中的,可以将其打上标记。

我们的目的是让这 \(k\) 个任务的 \(suma\) 最大,另外 \(p-k\) 个任务的 \(sumb\) 最大。然后我们将 \(n\) 个任务按照 \(x.a>y.a\) 排序,为了让这些被主席选上,我们要以 \(x.b>y.b\) 为第二排序。这样我们便找到了要让主席选上的 \(k\) 个任务,即排序后的前 \(k\) 个。

最后再按照第一种排序方式排序,选择已选中的 \(k\) 个任务后面的 \(p-k\) 个,这样既保证了按照 \(b\) 从大到小排序,又能使 \(p-k\) 个任务的 \(maxb\) 小于 \(k\) 个任务的 \(minb\) ,即主席一定会选我们选择好的 \(k\) 个任务。

代码

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100005
#define il inline
#define re register
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef long long ll;

template <typename T> inline void read(T &x) {
    T f = 1; x = 0; char c;
    for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    x *= f;
}

struct task {
    int a, b, id, tag;
} t[N];

int n, p, k, cnt, num;
bool vis[N];

bool pre(task x, task y) {
    if (x.b != y.b) return x.b < y.b;
    if (x.a != y.a) return x.a > y.a;
    return x.tag < y.tag;
}

bool stu(task x, task y) {
    return x.a == y.a ? x.b > y.b : x.a > y.a;
}

int main() {
    read(n), read(p), read(k);
    for (int i = 1; i <= n; ++i) read(t[i].a), read(t[i].b), t[i].id = i;
    sort(t + 1, t + 1 + n, pre);
    for (int i = 1; i <= p - k; ++i) t[i].tag = 1;
    sort(t + 1, t + 1 + n, stu);
    for (int i = 1; cnt < k; ++i)
        if (!t[i].tag) {
            cnt++;
            printf("%d ", t[i].id);
            vis[t[i].id] = 1;
            t[i].tag = 2;
        }
    cnt = 0;
    sort(t + 1, t + 1 + n, pre);
    for (int i = n; cnt < p - k; --i) {
        if (num >= k) {
            cnt++;
            printf("%d ", t[i].id);
        }
        if (vis[t[i].id]) num++;
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hlw1/p/11503125.html
今日推荐