题目内容
给出N把钥匙挂在挂架上,编号从左到右为1~N。然后给出K个老师的钥匙使用信息w, s, c,分别表示一位老师要使用的钥匙编号、开始上课的时间和上课的时长。还钥匙时每次都先放在挂架最左边的空位。借钥匙时就直接取下钥匙。如果同时有老师借和还,就先按钥匙编号从小到大还完后再借钥匙。老师使用钥匙的时间不会重叠。
样例输入
5 2
4 3 3
2 2 7
样例输出
1 4 3 2 5
样例输入
5 7
1 1 14
3 3 12
1 15 12
2 7 20
3 18 12
4 21 19
5 30 9
样例输出
1 2 3 5 4
思路
在输入数据时就建立时间轴,可以使用STL的set来建立,set自动从小到大排序;然后根据建立好的时间轴里,每个时间点都有动作发生,要么借,要么还。所以使用两个二维数组,borrow和restore数组,一维成员就是时间轴的点,二维成员就是要进行操作的钥匙。
注意,restore数组里面的钥匙要按编号从小到大排序。borrow就不用。
再使用一个map来记录每把钥匙的当前位置,供后续操作使用。然后再开始时建立一个挂架数组hanger来模拟当前挂架情况。
执行时以时间轴进行循环,循环结束后输出当前挂架hanger的钥匙情况即可。
C++代码
#include <iostream>
#include <vector>
#include <map>
#include <set>
using namespace std;
int main(){
int numberOfKey,numberOfTeacher;
int keyNum,start,duration,end;
cin >> numberOfKey >> numberOfTeacher;
int hanger[numberOfKey + 1];
map<int,int> key;
set<int> time;
set<int> emptyPos;
vector<vector<int> > borrow(10101);
vector<set<int> > restore(10101);
for(int i = 1; i <= numberOfKey; i++){
key[i] = i;
hanger[i] = i;
}
for(int i = 0; i < numberOfTeacher; i++){
cin >> keyNum >> start >> duration;
end = start + duration;
time.insert(start);
time.insert(end);
borrow[start].push_back(keyNum);
restore[end].insert(keyNum);
}
for(auto it = time.begin(); it != time.end(); it++){
if(restore[*it].size() != 0){// restore key
for(auto kt = restore[*it].begin();
kt != restore[*it].end(); kt++){
hanger[*emptyPos.begin()] = *kt;
key[*kt] = *emptyPos.begin();
emptyPos.erase(*emptyPos.begin());
}
}
if(borrow[*it].size() != 0)// borrow key
for(int i = 0; i < borrow[*it].size(); i++)
emptyPos.insert(key[borrow[*it][i]]);
}
for(int i = 1; i <= numberOfKey; i++){
if(i - 1)
cout << ' ';
cout << hanger[i];
}
return 0;
}