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

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

在这里插入图片描述

题目思路

  • mark数组用来存储第i号钥匙的位置,优先队列pq用来存取空挂钩的位置(每次取最左空位的时间复杂度为 O ( l o g n ) O(logn) ,比直接用线性表的 O ( n ) O(n) 要快速)
  • 我们把每次借用钥匙和归还钥匙的时刻都当作时间节点,这样我们就有 2 k 2*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;
} 
发布了59 篇原创文章 · 获赞 103 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_42292229/article/details/103445894