已经第二次出现这种OPT模拟的题目了,时间被卡到怀疑人生
第一次出现时统计置换次数
第二次出现是添加部分条件:同时存在最大值时按页面大的删除,最后输出操作结束后的结果,按照最原始的顺序输出。
贴上代码。
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f
struct node{
int pos, x;
node(){};
node(int pos,int x){
this->pos=pos;
this->x=x;
};
bool friend operator < (node xx,node yy){//排序要求
if(xx.pos==yy.pos)
return xx.x<yy.x;
return xx.pos<yy.pos;
}
};
int nextpos[500005];//这个位置的数字下一个出现的位置
int num[500005];//操作页面
int before[100005];//第i个数字的前一个位置
int numtopos[500005];//i各个数在缓存中的第几个位置
int ans[500005];//缓存中第i个位置是哪个数
set<node>s;
int c,a;
set<node>::iterator it;
int main()
{
std::ios::sync_with_stdio(false);
while(scanf("%d %d",&a,&c)!=EOF){
s.clear();
memset(nextpos,inf,sizeof(nextpos));
memset(before,0,sizeof(before));
for(int i=1;i<=a;i++){
int x;
scanf("%d",&x);
num[i]=x;
if(before[x]!=0)//多次出现过了这个数之后更新nextpos
nextpos[before[x]]=i;
before[x]=i;
}
int thispos,maxsize=0;
//节点保存的是下一个出现的位置,和这个数x
//每次查询之后,如果存在那么直接删除,再插入新节点更新这个数的下一个位置
//如果不存在,则需要从缓存中删除,直接删除集合最后的节点(因为本身就是按照要求排序的)
//每次找出删除节点的缓存中位置,更新该位置的值
//更新这个数在缓存中的第几个位置
for(int i=1;i<=a;i++){
it = s.find(node(i,num[i]));
if(it!=s.end()){
s.erase(it);
thispos = numtopos[num[i]];
}
else {
if(s.size()==c){
it=s.end();
it--;
thispos = numtopos[(*it).x];
s.erase(it);
}
else {
thispos=s.size();
}
}
s.insert(node(nextpos[i],num[i]));
ans[thispos]=num[i];
numtopos[num[i]]=thispos;
maxsize=max(maxsize,thispos);
}
for(int i=0;i<=maxsize;i++){
if(i!=0)printf(" ");
printf("%d",ans[i]);
}
printf("\n");
}
return 0;
}