一、区间问题
按左端点、或者右端点排序。
1.区间选点
运算符重载代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
struct Range{
int l, r;
bool operator< (const Range &W) const //重载小于号
{
return r < W.r; //右端点排序
}
}range[N];
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n); //区别,这里直接两个参数(有运算符重载过了)
int res = 0, ed = -2e9;
for (int i = 0; i < n; i++)
{
if (range[i].l > ed)
{
res++;
ed = range[i].r;
}
}
cout << res << endl;
return 0;
}
自己实现cmp比较逻辑的代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
struct Range{
int l, r;
}range[N];
bool cmp(const struct Range &A, const struct Range &B)
{
return A.r < B.r;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n, cmp); //区别,三个参数
int res = 0, ed = -2e9;
for (int i = 0; i < n; i++)
{
if (range[i].l > ed)
{
res++;
ed = range[i].r;
}
}
cout << res << endl;
return 0;
}
2.最大不相交区间数量
代码同第一问
证明:
3.区间分组
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 100010;
struct Range
{
int l, r;
}range[N];
bool cmp(Range &A, Range &B)
{
return A.l < B.l;
}
int main()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n, cmp);
priority_queue<int, vector<int>, greater<int>> q; //保存所有分组的最右侧端点值, 堆顶为最小的Max_r(最大右边界值)
for (int i = 0; i < n; i++)
{
auto t = range[i];
if(q.empty() || q.top() >= t.l) q.push(t.r); //和最小的Max_r都重合了,就只能开一个新的区间了
else{
q.pop();
q.push(t.r); //更新,加入新的(最大)最右边端点值
}
}
cout << q.size() << endl;
// while (!q.empty()) {
// auto t = q.top();
// q.pop();
// cout << t << endl;
// }
return 0;
}
4.区间覆盖
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int st, ed;
struct Range{
int l, r;
bool operator< (const Range &W) const
{
return l < W.l;
}
}range[N];
int main()
{
cin >> st >> ed;
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int l, r;
cin >> l >> r;
range[i] = {l, r};
}
sort(range, range + n);
int res = 0;
bool flag = false;
for(int i = 0; i < n; i++)
{
int j = i, r = -2e9;
while(j < n && range[j].l <= st) //找小于st的 最右边最大的区间
{
r = max(r, range[j].r);
j++;
}
if (r < st)
{
res = -1;
break;
}
res ++;
if (r >= ed)
{
flag = true;
break;
}
st = r;
i = j - 1;
}
if(!flag) res = -1;
cout << res << endl;
return 0;
}
二、其他问题
1.合并果子(哈夫曼树)
模拟一遍 最小两个数合并过程就可以
#include<queue>
priority_queue<int, vector<int>, greater<int>> q1; //小根堆
priority_queue<int> q; //大根堆
1、2、3比较简单, 按照题意找方法就行
4、耍杂技的牛
重点:推公式 w + s
ACM校赛永远的痛!