为了更好的阅读体检,可以查看我的算法学习网
在线评测链接:P1323
题目内容
天津大学允许学生自助预约会议室。小 C C C受邀对会议预约系统进行开发,他将获得一天的会议清单,现需要根据清单确定一天内最多有几场会议同时进行。
输入描述
多组测试样例,第一行包含一个整数T表示样例数。
每组样例第一行包含一个整数 N N N,表示会议清单共包含多少场会议,之后 N N N行每行包括两个数字[ s , t s, t s,t),表示会议将于 s s s开始 t t t结束。
输入描述
对于每一组输入,输出一个整数,表示今天最多同时进行的会议数。
样例
输入
2
2
1 3
3 5
3
3 5
1 4
4 5
输出
1
2
提示
单样例中会议内清单不超过 1000000 1000000 1000000条,数据保证 s < t s<t s<t,即终止时间必定大于开始时间,且 s s s, t t t保证在 i n t int int范围内。
思路:差分思想+sort实现
如果值域在 1 0 7 10^7 107 内,是可以通过开辟一个长度为 1 0 7 10^7 107 的数组直接差分进行 O ( 1 ) O(1) O(1) 更新,然后遍历所有值来更新答案的。
但是目前值域在 i n t int int 即 2 31 − 1 2^{31}-1 231−1 范围内,无法开这么大的数组。
但是我们进行差分数组统计后,依旧是按照从小到大的顺序来求解的。
所以我们将所有出现过的点按照大小排序。这样从小到大只需要遍历所有的会议开始和结束点,类似差分数组进行前缀和计算的过程。
最多同时会议的时间点必然是某场会议的开始时间点,因为一个会议的开始时间时,增加了正在进行的会议的数量,会议的中间时间段,同时进行的会议数量必然不会增多。
所以我们只需要考虑所有会议的开始时间点即可,但是由于一个点可能为会议A的开始时间点,也可能为会议B的结束时间点。这样直接遍历所有的会议开始结束时间点,然后更新得到答案即可。
如果不会前缀和与差分数组,建议学习 塔子哥的前缀和&差分数组。
代码
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
for (int ca = 0; ca < T; ++ca) {
int n;
cin >> n;
vector<pair<int, int>> vec;
for (int i = 0; i < n; ++i) {
int s, t;
cin >> s >> t;
vec.emplace_back(s, 1);
vec.emplace_back(t, -1);
}
// 按照第一关键字,即时间点从小到大排序,满足了差分的要求
// 按照第二关键字,即 -1 优先于 1
// 这样先把在每个时间点结束的会议给去除,然后加上这个时间点的所有会议,不会出现一个结束时间点结束的会议被累加到了答案中
sort(vec.begin(), vec.end());
int ans = 0;
for (int i = 0, sum = 0; i < vec.size(); ++i) {
sum += vec[i].second;
ans = max(ans, sum);
}
cout << ans << "\n";
}
return 0;
}
总结
本题介于简单到中等简单题之间,需要对差分有一定的了解,然后通过其本质来模拟差分进行前缀和计算的过程。