bzoj1826: [JSOI2010]缓存交换

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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值