当前位置: 代码迷 >> 综合 >> bzoj1826: [JSOI2010]缓存交换
  详细解决方案

bzoj1826: [JSOI2010]缓存交换

热度:101   发布时间:2023-10-29 11:17:29.0

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。

水题

就是贪心地吧下一次出现的地方最远的删掉就好了
正确性显然

#include<cstdio>
#include<cstdlib>
#include<queue>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=100005;
int n,m;
int a[N];
struct qq
{int id,x;
}b[N];
int next[N];//下一个是谁 
struct qt
{int x;bool operator < (qt a)const{return next[a.x]>next[x];};
};
int ooo[N];
bool cmp (qq a,qq b){
   return a.x<b.x;}
bool in[N];//这个点在不在
priority_queue<qt> q;
int main()
{scanf("%d%d",&n,&m);for (int u=1;u<=n;u++){scanf("%d",&b[u].x);b[u].id=u;}sort(b+1,b+1+n,cmp);int last=0,cnt=0;for (int u=1;u<=n;u++){if (b[u].x!=last) cnt++;a[b[u].id]=cnt;last=b[u].x;}memset(ooo,127,sizeof(ooo));for (int u=n;u>=1;u--){next[u]=ooo[a[u]];ooo[a[u]]=u;}
// for (int u=1;u<=n;u++) printf("%d ",a[u]);/*printf("\n");for (int u=1;u<=n;u++) printf("%d ",next[u]);*/memset(in,false,sizeof(in));int lalal=0;int ans=0;for (int u=1;u<=n;u++){if (in[a[u]]==true) {q.push(qt{u});continue;}if (lalal==m){while (!q.empty()){int hh=(q.top()).x;q.pop();if (in[a[hh]]==true){in[a[hh]]=false;break;}}}else lalal++;in[a[u]]=true;ans++;q.push(qt{u});}printf("%d\n",ans);return 0;
}