您的位置:首页 > 其它

ccf-csp #201709-2 公共钥匙盒

2020-04-07 18:29 1491 查看

题目链接:http://118.190.20.162/view.page?gpid=T62

题目思路

  • mark数组用来存储第i号钥匙的位置,优先队列pq用来存取空挂钩的位置(每次取最左空位的时间复杂度为O(logn)O(logn)O(logn),比直接用线性表的O(n)O(n)O(n)要快速)
  • 我们把每次借用钥匙和归还钥匙的时刻都当作时间节点,这样我们就有2∗k2*k2∗k个时间节点。依照题意,我们按时间从早到晚,结合归还优先、钥匙编号小的优先策略对所有时间节点进行排序
  • 接下来,只要遍历所有的时间节点,模拟借钥匙和还钥匙的操作就可以了。如果是借钥匙操作,就把空位在优先队列中记录。否则,在优先队列中读取最左边空挂钩的位置,放回钥匙并把该位置移出优先队列。

代码如下

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 2005;
//用于表示执行借用或者归还的时间点
struct Point{
int id, Time, isRet;//isRet等于0表示借用,等于1表示归还
} a[maxn];
int n, k, w, s, c;
//mark[i]表示i存放的位置
int mark[maxn], res[maxn];
//小根堆,表示从左到右的空位
priority_queue<int, vector<int>, greater<int> > pq;

bool cmp(const Point &A, const Point &B) {
if (A.Time == B.Time) {
if (A.isRet == B.isRet) {
return A.id < B.id;
} else {
return A.isRet > B.isRet;
}
} else {
return A.Time < B.Time;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++) mark[i] = i;
for (int i = 1; i <= k; i++) {
cin >> w >> s >> c;
a[(i<<1)-1].id = w;
a[(i<<1)-1].Time = s; //借用的时间节点
a[(i<<1)-1].isRet = 0;
a[i<<1].id = w;
a[i<<1].Time = s + c; //归还的时间节点
a[i<<1].isRet = 1;
}
sort(a + 1, a + k * 2 + 1, cmp);
int x = 0, y = 0;
for (int i = 1; i <= k * 2; i++) {
int key = a[i].id;
if (a[i].isRet) {
//return the key
mark[key] = pq.top();
pq.pop();
} else {
// borrow the key
pq.push(mark[key]);
}
}
for (int i = 1; i <= n; i++) res[mark[i]] = i;
for (int i = 1; i <= n; i++)
cout << res[i] << " ";
cout << endl;
return 0;
}
  • 点赞 2
  • 收藏
  • 分享
  • 文章举报
VeggieOrz 发布了89 篇原创文章 · 获赞 652 · 访问量 70万+ 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: