题解:P12166 [蓝桥杯 2025 省 C/Java A/研究生组] 冷热数据队列

思路

直接模拟。我不会写工程化代码。

考虑使用 list 模拟两个队列,不用 deque 一个原因是常数太大,另一个原因是貌似不支持删除中间元素。

操作一

\(p\) 不在队列 \(q\) 中(即既不在 \(q_1\) 中,也不在 \(q_2\) 中),则加载数据页 \(p\),并插入到 \(q_2\) 的首部。

我们考虑开一个 bitset 或者 bool 数组 \(vis\) 来记录对于某个 \(p\) 其是否在队列中。若 \(vis_i=0\),则在 \(q_2\) 的头部插入元素 \(p\),同时更新 \(vis_i\)

当然,为了后面的淘汰元素考虑,我们可以开一个桶存储元素所在的队列和其所在位置的迭代器。

实现

if(vis[x])
{
  // ...
}
else
{
  vis[x]=1;
  qb.push_front(x);
  _Mp[x]=make_pair(2,qb.begin());
}

操作二

\(p\) 已经在队列 \(q\) 中,则将 \(p\) 移动至 \(q_1\) 首部。

这时候我们前面记录的 \(vis\) 又起作用了。若 \(vis_i=1\),找到桶中记录的 \(p\) 所在的队列和指向 \(p\) 的迭代器,利用 erase 删除即可,删除迭代器貌似是 \(O(1)\) 的。最好不要使用 remove

删除后重新将 \(p\) 加入至 \(q_1\) 首部,此时和操作一中的步骤类似,记录下 \(p\) 所在的队列和其所在位置的迭代器。由于 \(vis_i\) 已经等于 \(1\),无需再更新。

实现

if(vis[x])
{
  auto tmp=_Mp[x];
  if(tmp.first==1)
    qa.erase(tmp.second);
  else
    qb.erase(tmp.second);
  qa.push_front(x);
  _Mp[x]=make_pair(1,qa.begin());
}

操作三

\(q_1\)\(q_2\) 队列容量不足时,会将其尾部的数据页淘汰出去。

和操作四一起实现。

操作四

\(q_1\) 已满,但 \(q_2\) 未满时,从 \(q_1\) 中淘汰出的数据页会移动到 \(q_2\) 首部。

由于 \(q_1\) 淘汰的元素会移动到 \(q_2\),不妨考虑先淘汰 \(q_1\) 中的元素,若加入 \(q_2\) 后导致 \(q_2\) 满了,再淘汰 \(q_2\) 中的最后一个元素。list 自带 rbegin 返回指向最后一个元素的迭代器。

同样地,记录元素所在的队列及指向这个元素的迭代器,注意 \(q_2\) 淘汰的元素的 \(vis\) 值应当变为 \(0\)

实现

if(qa.size()>na)
{
  auto tmp=*qa.rbegin();
  qb.push_front(tmp);
  _Mp[tmp]=make_pair(2,qb.begin());
  qa.pop_back();
}
if(qb.size()>nb)
{
  auto tmp=*qb.rbegin();
  vis[tmp]=0;
  qb.pop_back();
}

输出

遍历两个链表即可。

实现

for(auto i:qa)
  printf("%d ",i);
printf("\n");
for(auto i:qb)
  printf("%d ",i);
printf("\n");

代码

算上我又臭又长的缺省源总共六十多行。非常好写。

#include <bits/stdc++.h>
//#include <bits/extc++.h>
//#define int long long
#define __MULTITEST__
#undef __MULTITEST__
using namespace std;
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;
int na,nb,m;
list<int> qa,qb;
bitset<100005> vis;
pair<int,list<int>::iterator> _Mp[100005];
signed main()
{
	#ifdef __MULTITEST__
	signed T;
	scanf("%d",&T);
	while(T--)
	{
	#endif
		scanf("%d%d%d",&na,&nb,&m);
		for(int i=1;i<=m;i++)
		{
			int x;
			scanf("%d",&x);
			if(vis[x])
			{
				auto tmp=_Mp[x];
				if(tmp.first==1)
					qa.erase(tmp.second);
				else
					qb.erase(tmp.second);
				qa.push_front(x);
				_Mp[x]=make_pair(1,qa.begin());
			}
			else
			{
				vis[x]=1;
				qb.push_front(x);
				_Mp[x]=make_pair(2,qb.begin());
			}
			if(qa.size()>na)
			{
				auto tmp=*qa.rbegin();
				qb.push_front(tmp);
				_Mp[tmp]=make_pair(2,qb.begin());
				qa.pop_back();
			}
			if(qb.size()>nb)
			{
				auto tmp=*qb.rbegin();
				vis[tmp]=0;
				qb.pop_back();
			}
		}
		for(auto i:qa)
			printf("%d ",i);
		printf("\n");
		for(auto i:qb)
			printf("%d ",i);
		printf("\n");
	#ifdef __MULTITEST__
	}
	#endif
	return 0;
}
posted @ 2025-04-17 22:58  Amidst  阅读(53)  评论(0)    收藏  举报