方法来自书上,这题让我想起了先前做过的一道题,都是分组问题.
按照开始吃草的时间将牛排序,使用一个小根堆,存储每个畜栏最后一头牛结束吃草的时间.
对于每一头牛,尝试将其加入到堆顶对应的畜栏,如果失败则需要一个新的畜栏.
所以,在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; }