解题思路
这个问题描述了一个关于管理和还取钥匙的过程,在一个学校中,所有的教室钥匙都必须放在公共钥匙盒里,老师上课需要用到钥匙时,会从钥匙盒中取出,上完课后再将钥匙还回。题目要求根据给定的教师使用钥匙的时间安排,计算出最终钥匙盒内钥匙的顺序。
-
初始化钥匙盒:首先,根据钥匙的总数N,初始化钥匙盒,每个挂钩上挂的钥匙编号是从1到N的顺序。
-
读取和处理输入:接下来,根据老师的数量K,读取每位老师使用钥匙的编号、开始上课的时间以及上课的时长。对于每位老师,会有两个关键时间点:取钥匙的时间和还钥匙的时间。这两个时间点分别对应一个操作:取钥匙(operate=0)和还钥匙(operate=1)。每个操作都记录下来,包括操作的时间、类型(取或还)、以及钥匙编号。
-
排序操作:将所有的操作(包括取钥匙和还钥匙的操作)按时间顺序进行排序。如果两个操作发生在同一时间,还钥匙的操作优先于取钥匙的操作进行,如果还是相同,按钥匙编号顺序进行。这是因为题目规定如果同一时刻有老师还钥匙和取钥匙,应该先还后取。
-
执行操作:遍历排序后的操作列表,根据操作的类型(取或还),更新钥匙盒的状态。当老师取钥匙时,找到该钥匙并标记为已取出(例如,可以设置为-1表示钥匙不在盒子中)。当老师还钥匙时,找到最左边的空挂钩,将钥匙挂回。这里,空挂钩也是用-1表示。
-
输出结果:遍历钥匙盒,打印每个挂钩上的钥匙编号,这就是最终的钥匙排列顺序。
完整代码
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;
struct key
{
int time;
int operate; // 0-get 1-back
int index;
};
bool cmp(key&a,key&b)
{
if (a.time == b.time)
{
if (a.operate && (!b.operate)) // back A
return true;
else if ((!a.operate) && b.operate) // back B
return false;
else if (a.operate == b.operate)
return a.index < b.index;
}
else
return a.time < b.time;
}
int N, K, w, s, c;
int main()
{
cin >> N >> K;
vector<int> box(N);
for (size_t i = 0; i < N; i++)
{
box[i] = i + 1;
}
vector<key> opt(2 * K);
for (size_t i = 0; i < K; i++)
{
cin >> w >> s >> c;
opt.push_back({s, 0, w});
opt.push_back({s + c, 1, w});
}
sort(opt.begin(), opt.end(), cmp);
for (auto &it : opt)
{
if (it.operate) // back
{
for (auto &jt : box)
{
if (jt == -1)
{
jt = it.index;
break;
}
}
}
else // get
{
for (auto &jt : box)
{
if (jt == it.index) // find key
{
jt = -1;
break;
}
}
}
}
for (auto &it : box)
{
cout << it << " ";
}
return 0;
}