Description
在计算机中,CPU只能和高速缓存Cache直接交换数据。当所需的内存单元不在Cache中时,则需要从主存里把数据调入Cache。此时,如果Cache容量已满,则必须先从中删除一个。
例如,当前Cache容量为3,且已经有编号为10和20的主存单元。 此时,CPU访问编号为10的主存单元,Cache命中。
接着,CPU访问编号为21的主存单元,那么只需将该主存单元移入Cache中,造成一次缺失(Cache Miss)。
接着,CPU访问编号为31的主存单元,则必须从Cache中换出一块,才能将编号为31的主存单元移入Cache,假设我们移出了编号为10的主存单元。
接着,CPU再次访问编号为10的主存单元,则又引起了一次缺失。我们看到,如果在上一次删除时,删除其他的单元,则可以避免本次访问的缺失。
在现代计算机中,往往采用LRU(最近最少使用)的算法来进行Cache调度——可是,从上一个例子就能看出,这并不是最优的算法。
对于一个固定容量的空Cache和连续的若干主存访问请求,聪聪想知道如何在每次Cache缺失时换出正确的主存单元,以达到最少的Cache缺失次数。
Input
输入文件第一行包含两个整数N和M(1<=M<=N<=100,000),分别代表了主存访问的次数和Cache的容量。
第二行包含了N个空格分开的正整数,按访问请求先后顺序给出了每个主存块的编号(不超过1,000,000,000)。
Output
输出一行,为Cache缺失次数的最小值。
Sample Input
6 2
1 2 3 1 2 3
Sample Output
4
HINT
在第4次缺失时将3号单元换出Cache。
题解
先离散化再贪心一下
设第i个位置下一个相同的单元是nxt[i],如果没有的话nxt[i]=n+1
那每次弹出肯定是弹出nxt[i]最大的
那你可以搞一个可删堆,维护nxt[i]
然后又是随便做了。。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct LSnode{int y,p;}w[110000];
bool cmp(LSnode n1,LSnode n2){return n1.y<n2.y;}
int pla[110000];
struct node
{
int pla;
friend bool operator <(node n1,node n2){return n1.pla<n2.pla;}
};
struct heap
{
priority_queue<node> A,B;
void push(node x){A.push(x);}
void pop()
{
node tx,ty;
tx=A.top();
if(B.size())ty=B.top();
while(tx.pla==ty.pla && B.size()){A.pop();B.pop();tx=A.top();ty=B.top();}
A.pop();
}
void erase(node x){B.push(x);}
node top()
{
node tx,ty;
tx=A.top();
if(B.size())ty=B.top();
while(tx.pla==ty.pla && B.size()){A.pop();B.pop();tx=A.top();ty=B.top();}
return A.top();
}
}q;
int nxt[110000],las[110000];
int n,m,col[110000];
bool vis[110000];
int main()
{
// freopen("swap10.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",&w[i].y),w[i].p=i;
sort(w+1,w+1+n,cmp);
int tt=1;col[w[1].p]=1;
for(int i=2;i<=n;i++)
{
if(w[i].y!=w[i-1].y)tt++;
col[w[i].p]=tt;
}
memset(las,-1,sizeof(las));
for(int i=n;i>=1;i--)
{
if(las[col[i]]==-1)nxt[i]=n+1,las[col[i]]=i;
else nxt[i]=las[col[i]],las[col[i]]=i;
}
memset(vis,false,sizeof(vis));
int ans=0,cnt=0,beg=-1;
for(int i=1;i<=n;i++)
{
if(!vis[col[i]])
{
if(cnt==m){beg=i;break;}
vis[col[i]]=true;
ans++;cnt++;
node tmp;tmp.pla=nxt[i];
q.push(tmp);
}
else
{
node tmp;
tmp.pla=i;q.erase(tmp);
tmp.pla=nxt[i];q.push(tmp);
}
if(cnt==m){beg=i+1;break;}
}
if(beg==-1)printf("%d\n",ans);
else
{
for(int i=beg;i<=n;i++)
{
if(!vis[col[i]])
{
vis[col[i]]=true;ans++;
node tmp;
tmp=q.top();
if(tmp.pla!=n+1)vis[col[tmp.pla]]=false;
q.pop();
tmp.pla=nxt[i];
q.push(tmp);
}
else
{
node tmp;
tmp.pla=i;q.erase(tmp);
tmp.pla=nxt[i];q.push(tmp);
}
}
printf("%d\n",ans);
}
return 0;
}