暂无。。。
暂无。。。
题目1:区间选点。给你N个区间,让你在数轴上选一些点,要求N个区间中至少有一个点被选出。求选一些点的最少数目。
解题思路:贪心,按照右端点排序,每次选择右端点,维护一个res
和右端点right
即刻,如果当前区间左端点大于right
,则更新right
,res
自增。
C++代码如下,
#include
#include
#include
using namespace std;
int main() {
int n;
cin >> n;
vector<pair<int,int>> nums;
for (int i = 0; i < n; ++i) {
int a, b;
cin >> a >> b;
nums.emplace_back(a,b);
}
sort(nums.begin(), nums.end(), [](const pair<int,int> a, const pair<int,int> b) {
return a.second < b.second;
});
int res = 0;
int right = -2e9;
for (auto [x,y] : nums) {
if (x > right) {
res += 1;
right = y;
}
}
cout << res << endl;
return 0;
}
题目2:求最大不相交区间数。给定N个区间,你可以选择一些区间,要求这些区间不能相交,求区间的最大数目。
解题思路:同题目1的解题思路。
C++代码如下,
#include
#include
#include
using namespace std;
int main() {
int n;
cin >> n;
vector<pair<int,int>> nums;
for (int i = 0; i < n; ++i) {
int a, b;
cin >> a >> b;
nums.emplace_back(a,b);
}
sort(nums.begin(), nums.end(), [](const pair<int,int> a, const pair<int,int> b) {
return a.second < b.second;
});
int res = 0;
int right = -2e9;
for (auto [l, r] : nums) {
if (l > right) {
res += 1;
right = r;
}
}
cout << res << endl;
return 0;
}
题目3:给你N个区间,请将它们分成若干组,要求每组内部两两区间互不相交,求组数目的最小值。
关键步骤介绍如下:
heap
,用来存储每个组中所有区间右端点的最大值。C++代码如下,
#include
#include
#include
#include
using namespace std;
int main() {
int n;
cin >> n;
vector<pair<int,int>> nums;
for (int i = 0; i < n; ++i) {
int a, b;
cin >> a >> b;
nums.emplace_back(a,b);
}
sort(nums.begin(), nums.end());
priority_queue<int, vector<int>, greater<int>> heap;
for (auto [l, r] : nums) {
if (heap.empty() || heap.top() >= l) {
heap.push(r);
} else {
heap.pop();
heap.push(r);
}
}
cout << heap.size() << endl;
return 0;
}
题目4:给定N个区间和一个[s,t],求能把[s,t]完全覆盖住的最少区间数目。
解题关键步骤:
int start = st
和int res = 0
。int r = -2e9
,在所有能覆盖住start的区间中(即nums[j].first <= start
),选择右端点最大的区间(即r = max(r, nums[j].second)
)。如果r < start
,说明无法覆盖住,终止循环break
。然后res += 1
和start = r
,如果start >= ed
,提前终止循环,返回答案res
。C++代码如下,
#include
#include
#include
using namespace std;
int main() {
int st, ed;
cin >> st >> ed;
int n;
cin >> n;
vector<pair<int,int>> nums;
for (int i = 0; i < n; ++i) {
int a, b;
cin >> a >> b;
nums.emplace_back(a,b);
}
//按照左端点排序
sort(nums.begin(), nums.end(), [](const pair<int,int> a, const pair<int,int> b) {
return a.first < b.first;
});
int res = 0;
int start = st;
bool is_succ = false;
for (int i = 0; i < nums.size(); ++i) {
int r = -2e9;
int j = i;
while (j < nums.size() && nums[j].first <= start) {
r = max(r, nums[j].second);
j += 1;
}
if (r < start) { //最左侧的区间的左端点都大于start,无法覆盖住
break;
}
res += 1;
start = r;
if (start >= ed) {
is_succ = true;
break;
}
i = j - 1;
}
if (is_succ) cout << res << endl;
else cout << -1 << endl;
return 0;
}
题目5:合并果子。给你N堆不同数量的果子,每次可以选择任意两堆进行合并,合并代价和那两堆果子的数目之和。求将N堆果子合并成一堆果子的最小代价。
解题思路:贪心做法,每次选择最小的两堆进行合并。
C++代码为,
#include
#include
#include
using namespace std;
int main() {
int n;
cin >> n;
priority_queue<int, vector<int>, greater<int>> heap;
while (n--) {
int x;
cin >> x;
heap.push(x);
}
int res = 0;
while (heap.size() > 1) {
int a = heap.top(); heap.pop();
int b = heap.top(); heap.pop();
res += a + b;
heap.push(a + b);
}
cout << res << endl;
return 0;
}