思路
- 一共有k节课,每节课要借一次和还一次,即借k次、还k次
- 每节课有开始时间(借)和结束时间(还)
- 分别对借和还排序,都是按照时间从小到大排序,注意在还时,如果结束时间相同,则按照教室编号从小到大排序
- 借和还分别,两个计数器分别从1开始遍历k节课,如果当前借操作的时间小于还操作,则进行借操作,如果当前借操作的时间大于还操作,则进行还操作,如果二者相等,则先还再借
- 借操作:将开始时间等于当前时间的课的钥匙都取出,计数器移到下一个时间点
- 还操作:将结束时间等于当前时间的课的钥匙依次放入第一个空位置(已经按教室编号从小到大排序过),计数器移到下一个时间点
- 肯定是借的计数器先遍历完,最后只有还操作,因此只有在借计数器遍历完之前才比较借和还的时间大小,借遍历完之后只有还存在
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n, k, v[1005], v1[1005], v2[1005], no[1005], start[1005], end[1005];
int now_jie, now_huan;
bool cmp1(int a, int b)
{
return start[a] < start[b];
}
bool cmp2(int a, int b)
{
if(end[a] == end[b]) return no[a] < no[b];
else return end[a] < end[b];
}
void jie()
{
int now_time = start[v1[now_jie]];
for(now_jie; now_jie <= k && (start[v1[now_jie]] == now_time); ++now_jie)
{
for(int j = 1; j <= n; ++j)
{
if(v[j] == no[v1[now_jie]])
{
v[j] = 0;
break;
}
}
}
}
void huan()
{
int now_time = end[v2[now_huan]];
for(now_huan; now_huan <=k && end[v2[now_huan]] == now_time; ++now_huan)
{
for(int j = 1; j <= n; ++j)
{
if(v[j] == 0)
{
v[j] = no[v2[now_huan]];
break;
}
}
}
}
int main()
{
cin >> n >> k;
for(int i = 1; i <= n; ++i)
v[i] = i;
for(int i = 1; i <= k; ++i)
v1[i] = v2[i] = i;
for(int i = 1; i <= k; ++i)
{
scanf("%d%d%d", no + i, start + i, end + i);
end[i] += start[i];
}
sort(v1 + 1, v1 + 1 + k, cmp1);
sort(v2 + 1, v2 + 1 + k, cmp2);
now_jie = now_huan = 1;
while(now_jie <= k)
{
int u1 = v1[now_jie], u2 = v2[now_huan];
if(start[u1] < end[u2])
jie();
else if(start[u1] >end[u2])
huan();
else
{
huan();
jie();
}
}
while(now_huan <= k)
huan();
for(int i = 1; i <= n; ++i)
printf("%d ", v[i]);
cout << endl;
return 0;
}