洛谷P1233 [木棍加工]

戳这里看原题


主要思路:

这道题一眼看过去就可以贪心。。

首先可以按L排序。。

显然排序之后我们就可以抛开L不管了。。

然后就可以愉快的贪心了。。


细节:

这道题可以看成用 最少的合法序列(详见原题) 装下所有木棍。。

可以考虑用一种数据结构来记录序列最末端的木棍。。

可以考虑先按上述思路排序,

然后每次加木棍时加在第一个大于等于当前木棍宽度的木棍的序列末端,

然后顶替掉找到的这一位。

如果找不到这样的木棍就再开一个序列。。 (本题贪心的核心思想)

然而我懒得多动手,就用了STL的set来维护每个序列的末端木棍的宽度。。

set是C++中自带的红黑树(二叉平衡树),可以很方便地查找、插入和删除。

时间复杂度都是log级别。。

显然时间复杂度O(nlogn), 空间复杂度O(n)

剩下就是代码的事了。。(带注释):

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 5000;
 4 int n, ans;
 5 struct P {
 6     int a, b;
 7     friend bool operator < (P x, P y) { //set套结构体要重载<运算符
 8         return x.b < y.b;
 9     }
10 }s[N + 1];
11 bool cmp(P x, P y) { //将木棍按长度排序
12     if(x.a != y.a) return x.a > y.a;
13     return x.b > y.b;
14 }
15 set<P>a;
16 set<P>::iterator it; //定义一个set<P>的迭代器
17 int main() {
18     scanf("%d", &n);
19     for(int i = 1; i <= n; i++) 
20         scanf("%d%d", &s[i].a, &s[i].b);
21     sort(s + 1, s + 1 + n, cmp); //按照长度排序
22     for(int i = 1; i <= n; i++) {
23         if(a.empty()) a.insert(s[i]), ans++; //一定要这一步,不然没有元素时直接lower_bound会RE
24         else {
25             it = a.lower_bound(s[i]); //用lower_bound找到第一个大于等于当前木棍宽度的木棍
26             if(it == a.end()) a.insert(s[i]), ans++; //没有这样的木棍就再开一个序列
27             else a.erase(it), a.insert(s[i]); //否则就不用开,然后把这个木棍顶替掉之前这个序列的末尾木棍
28         }
29     }
30     printf("%d
", ans); //输出答案(实际上就是a.size())
31     return 0;
32 }
View Code
原文地址:https://www.cnblogs.com/aha--CYJ/p/8395016.html