T229990 题解

题目大意:

每次上课需要对应的书而每次回寝室只能拿一本,身上最多带k本,告诉你上课的顺序后求出最少回寝室的次数。

思路:

考虑贪心,显然如果身上满k本书后回寝室拿书一定是把一本下次需要用到的时间最靠后的书换掉。所以就需要求出每本书所需要用到的下一次时间也就是这门课下一次上的时间预先处理出来,然后通过一个优先队列存储身上k本书下一次需要用到的时间,这样就能最快的找到一本下一次用到的时间最靠后的书,然后将它替换掉,最后输出答案。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
map<int,int>mp;//存上课的时间
map<int,int>m;//标记当前课的书在不在身上
int ne[100005];//存这门课下一次上的时间
int a[100005];
int n,k;
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=n;i>=1;i--){//倒着遍历
		//如果这节课在之后不会在上了
		if(!mp[a[i]]){
			mp[a[i]]=i;//更新这门课上的时间
			ne[i]=99999999;//附一个很大的值表示这门课不会再上了
		}
		//反之这节课在后面还有
		else {
			ne[i]=mp[a[i]];//赋值为下一次这门课上的时间
			mp[a[i]]=i;//更新这门课上的时间
		}
	}
	int ans=0;
	int num=0;//身上书的数量
	priority_queue<int,vector<int>,less<int> >q;//优先队列
	for(int i=1;i<=n;i++){
		if(!m[a[i]]){//这本书不在身上
			if(num<k){//如果身上的书还没到k本
				q.push(ne[i]);//将这本书加到队列中
				m[a[i]]=1;//标记身上现在有这本书
				num++;//身上书的数量+1
			}
			else {//如果身上已经有k本书了
				if(q.top()!=99999999){//如果队首的这门课还要上
					m[a[q.top()]]=0;//将身上的这本书去掉
				}
				q.pop();//将队首去掉
				q.push(ne[i]);//把当前加进去的这本书的下次要用的时间加进队列
				m[a[i]]=1;//标记身上现在有当前这门课的书
			}
			ans++;//回寝室次数+1
		}
		else {//反之如果这本书在身上
			q.push(ne[i]);//把这本书下次要用的时间直接加进优先队列并且因为这本书已经在身上了所以不用回寝室
		}
	}
	cout<<ans;//输出答案
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值