贝壳2018 教室占用冲突
1、题目描述:
n个社团占用同一间教室,占用时间分别为 [li, ri]。占用时间可能发生冲突,去掉其中一个社团的申请后不发生冲突的方法有几种。
输入:
第一行:整数n,表示社团数。(1 <= n <= 5000)
第二行:n个区间,代表第i个社团的占用时间范围[li, ri]。
输出:
第一行:整数m,代表删除方式的数量。(每次只能删除一个社团)
第二行:m个整数,可以删除的社团编号,从小到大排列。
样例输入1:
3
3 10
20 30
1 3
样例输出1:
3
1 2 3
样例输入2:
4
3 10
20 30
1 3
1 39
样例输出2:
1
4
样例输入3:
3
1 5
2 6
3 7
样例输出3:
0
*/
2、题解-敲代码
1、对所有区间,按左边界进行排序,产生升序序列;
2、遍历升序序列,找到第一个冲突点(有前后两个社团发生冲突,”前一个社团“ 的右边界 > ”后一个社团“ 的左边界),记录这两个社团;以 “后一个社团” 的下一个社团作为 “新起点”,开始继续遍历比较,如果有第二个冲突点,则冲突无法避免,返回0;
3、如果整个遍历没有发生冲突,则无冲突,返回0;
4、如果只发生了一次冲突
(1)判断 “前一个社团” 是否和 ”新起点“ 及其之后的社团发生冲突
(2)判断 “后一个社团” 是否和 ”新起点“ 及其之后的社团发生冲突
(3)如果两个都与后面发生冲突,则冲突无法避免,返回0;
(4)如果两个都不与后面发生冲突,则删除任意一个社团都可以避免冲突,返回2;
(4)如果只有一个冲突,另一个不冲突,则删除冲突的那一个,返回1。
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
multimap<int, vector<int>> mp; //{li, {ri, i}} 左,右,编号
for (int i = 0; i < n; i++)
{
int x, y;
cin >> x >> y;
mp.insert({ x,{y, i+1} });
}
bool first_conflict = 0;
auto it11 = mp.end(); //记录冲突点第一个社团
auto it22 = it11; //记录冲突点第二个社团
for (auto it1 = mp.begin(); it1 != --mp.end(); it1++) //
{
auto it2 = next(it1);
if (it1->second[0] > it2->first) //冲突
{
if (first_conflict == 0) //是第一次发生冲突
{
it11 = it1;
it22 = it2;
first_conflict = 1;
it1 = it2;//跳过it1, it2,判断后面是否还会发生冲突
}
else //第二次发生冲突
{
cout << 0;
return 0;
}
}
}
if (first_conflict == 0) //一次冲突也没有发生
{
cout << n << endl;
for (int i = 1; i <= n; i++)
{
if (i < n)
cout << i << ' ';
else
cout << i;
}
return 0;
}
//对于只发生一次冲突,分别将发生冲突的社团放入,查看是否会避免冲突
int flag1 = 1;
int flag2 = 1;
if (next(it22) == mp.end() || it11->second[0] <= next(it22)->first) //it11与之后的社团比较,查看是否会避免冲突
{
//it11不冲突
flag1 = 0;
}
if (next(it22) == mp.end() || it22->second[0] <= next(it22)->first) //it22与之后的社团比较,查看是否会避免冲突
{
//it22不冲突
flag2 = 0;
}
if (flag1 && flag2) //两个都与后面冲突,删除任意一个都无效
{
cout << 0;
}
else if (!flag1&& !flag2) //两个都不与后面冲突,则删除任意一个即可
{
vector<int> ans = { it11->second[1], it22->second[1] };
sort(ans.begin(), ans.end());
cout << 2 << endl;
cout << ans[0] << ' ' << ans[1];
}
else if(flag1 && !flag2) //11与后面冲突,22与后面不冲突
{
cout << 1 << endl;
cout << it11->second[1];
}
else if (!flag1 && flag2) //11与后面不冲突,22与后面冲突
{
cout << 1 << endl;
cout << it22->second[1];
}
return 0;
}