zoukankan      html  css  js  c++  java
  • BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心

    BZOJ_1826_[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。


    考虑x数某次出现的位置到它下一次出现的位置这段区间。

    如果我想要让x不缺失,需要在这段区间里让x进入cache,相当于在这个区间(左开右开)塞一个数。

    那么整个序列中,每个位置中最多能塞入m-1个数,因为x这个数已经在cache里了。

    然后就变成了另一道题:http://www.cnblogs.com/suika/p/8711400.html

    代码:

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    #define N 200050
    #define ls p<<1
    #define rs p<<1|1
    int n,m;
    int t[N<<2],add[N<<2],now[N],tot;
    struct A {
        int num,id,v;
    }a[N];
    struct node {
        int l,r;
    }b[N];
    bool cmp1(const A &x,const A &y){return x.num<y.num;}
    bool cmp2(const A &x,const A &y){return x.id<y.id;}
    bool cmp3(const node &x,const node &y) {
        if(x.r==y.r) return x.l>y.l;
        return x.r<y.r;
    }
    void pushdown(int p) {
        if(add[p]) {
            int d=add[p];
            add[ls]+=d; t[ls]+=d;
            add[rs]+=d; t[rs]+=d;
            add[p]=0;
        }
    }
    void build(int l,int r,int p) {
        t[p]=m-1;
        if(l==r) {return ;}
        int mid=(l+r)>>1;
        build(l,mid,ls); build(mid+1,r,rs);
    }
    int query(int l,int r,int x,int y,int p) {
        if(x<=l&&y>=r) return t[p];
        int mid=(l+r)>>1,re=1<<30;
        pushdown(p);
        if(x<=mid) re=min(re,query(l,mid,x,y,ls));
        if(y>mid) re=min(re,query(mid+1,r,x,y,rs));
        t[p]=min(t[ls],t[rs]);
        return re;
    }
    void update(int l,int r,int x,int y,int v,int p) {
        if(x<=l&&y>=r) {
            t[p]+=v; add[p]+=v;
            return ;
        }
        pushdown(p);
        int mid=(l+r)>>1;
        if(x<=mid) update(l,mid,x,y,v,ls);
        if(y>mid) update(mid+1,r,x,y,v,rs);
        t[p]=min(t[ls],t[rs]);
    }
    int main() {
        memset(t,0x3f,sizeof(t));
        scanf("%d%d",&n,&m);
        int i;
        for(i=1;i<=n;i++) {
            scanf("%d",&a[i].num); a[i].id=i;
        }
        sort(a+1,a+n+1,cmp1);
        int j=0;a[0].num=1<<30;
        for(i=1;i<=n;i++) {
            if(a[i].num!=a[i-1].num)j++;
            a[i].v=j;
        }
        sort(a+1,a+n+1,cmp2);
        int ans=n;
        for(i=n;i>=1;i--) {
            if(now[a[i].v]) {
                b[++tot].l=i+1;
                b[tot].r=now[a[i].v]-1;
                if(b[tot].l>b[tot].r) tot--,ans--;
            }
            now[a[i].v]=i;
        }
        sort(b+1,b+tot+1,cmp3);
        build(1,n,1);
        for(i=1;i<=tot;i++) {
            int re=query(1,n,b[i].l,b[i].r,1);
            if(re>=1) {
                update(1,n,b[i].l,b[i].r,-1,1);
                ans--;
            }
        }
        printf("%d
    ",ans);
    }
    
  • 相关阅读:
    Android Widget桌面组件创建
    Android 音乐播放器。
    android 创建实时文件夹
    Android 中访问网页 webView
    Android 添加快捷方式
    Android闹钟设置
    Android中webView与javascript交互
    Android 通信的桥梁 Intent
    Android 中Notification和NotificationManager的使用
    Android中播放视频
  • 原文地址:https://www.cnblogs.com/suika/p/8997657.html
Copyright © 2011-2022 走看看