常见问题分类:
1)区间问题
2)Huffman
3)排序不等式
4)绝对值不等式
5)推公式
一、区间问题
板子:
①区间选点问题
#include <iostream> #include <algorithm> using namespace std; const int N = 1e5 + 10; struct Range{ int l, r; bool operator< (const Range& b) const{ return r < b.r; } }range[N]; int main(){ int n; cin >> n; int res = 0; for(int i = 0; i < n; i ++){ int l, r; cin >> l >> r; range[i] = {l , r}; } sort(range, range + n); int p = -2e9; for(int i = 0; i < n; i ++) if(p < range[i].l){ res ++; p = range[i].r; } cout << res; return 0; }
②区间分组
#include<iostream> #include<algorithm> #include<queue> using namespace std; const int N = 1e5 +10; struct Range{ int l, r; bool operator<(const Range& b)const { return l < b.l; } }range[N]; int n; int main(){ cin >> n; priority_queue<int, vector<int>, greater<int>> heap; // 小根堆 for(int i = 0; i < n; i ++){ int l, r; cin >> l >> r; range[i] = {l, r}; } sort(range, range + n); for(int i = 0; i < n; i ++){ if(heap.empty() || heap.top() >= range[i].l){ heap.push(range[i].r); }else{ // 直接接到最先结束的队伍后面 heap.pop(); heap.push(range[i].r); } } cout << heap.size(); return 0; }
③区间覆盖问题
#include<iostream> #include<algorithm> using namespace std; const int N = 1e5 + 10; struct Range{ int l, r; bool operator<(const Range& b) const { return l < b.l; } }range[N]; int n, res; int st, ed; int main(){ cin >> st >> ed; cin >> n; for(int i = 0; i < n; i ++){ int l, r; cin >> l >> r; range[i] = {l, r}; } sort(range, range + n); bool success = false; for(int i = 0; i < n; i ++){ int j = i, r = -2e9; // j从当前下标开始找,贪心到r最远能到的区间 while(j < n && range[j].l <= st){ // 能接得上 r = max(r, range[j].r); // 求出在接得上的前提下能够到达的最远距离 j ++; } if(r < st){ //在接得上的前提下能够到达的最远距离小于上一个线段的末尾 res = -1; break; // 则说明无法覆盖 } res ++; if(r >= ed){ success = true; break; } i = j - 1; st = r; } if(!success) res = -1; cout << res; return 0; }
Leetcode 3111.覆盖所有点的最少矩形数目
class Solution {
public:
int minRectanglesToCoverPoints(vector<vector<int>>& points, int w) {
int n = points.size();
long long res = 0;
sort(points.begin(), points.end(), [&](const vector<int>& a, const vector<int>& b) -> bool{
return a[0] < b[0];
}); // 按照x坐标进行排序
int st = points[0][0];
int cur_l = st, cur_r = cur_l + w; res ++;
for (int i = 0; i < n; i ++){
if (points[i][0] <= cur_r) continue;
// 否则需要新开一个区间
cur_r = points[i][0] + w; res ++;
}
return res;
}
};