AcWing 畜栏预定

方法来自书上,这题让我想起了先前做过的一道题,都是分组问题.

按照开始吃草的时间将牛排序,使用一个小根堆,存储每个畜栏最后一头牛结束吃草的时间.

对于每一头牛,尝试将其加入到堆顶对应的畜栏,如果失败则需要一个新的畜栏.

所以,在O(nlogn)快排之后,对于每头牛都进行O(logn)的操作(堆的push, pop),最终复杂度是O(nlogn).这题n2已经上亿了,线性扫描畜栏的方法会TLE.

此外,学习一下如何创建一个以结构体为元素的堆并对其进行操作.技巧总结在此.

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;

int n, ct, ans[50010];
struct S {
    int begin, end, num;
} t[50010];

struct node {
    int val, num;
};
struct cmp {
    bool operator()(const node &a, const node &b) { return a.val > b.val; }
};
priority_queue<node, vector<node>, cmp> q;

bool cmpS(S a, S b) { return a.begin < b.begin; }

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &t[i].begin, &t[i].end);
        t[i].num = i;
    }
    sort(t + 1, t + n + 1, cmpS);

    for (int i = 1; i <= n; i++) {
        bool bad = true;
        // for (int j = 1; j <= ct; j++)
        int to;
        if(!q.empty()) {
            to = q.top().num;
            if (t[i].begin > q.top().val) {
                ans[t[i].num] = to;
                q.pop();
                q.push({t[i].end, to});
                bad = false;
            }
        }

        if (bad) {
            ct++;
            q.push({t[i].end, ct});
            ans[t[i].num] = ct;
        }
    }

    printf("%d
", ct);
    for (int i = 1; i <= n; i++) printf("%d
", ans[i]);

    return 0;
}
原文地址:https://www.cnblogs.com/Gaomez/p/14180592.html