• BZOJ1206虚拟内存[hash]


    题目。。很长。。我一开始还没有理解。。语文果然有待加强的节奏啊~

    思路大概如下:

    n是10000,m是1000000,但是pi会有1e9,那么就是需要离散化的节奏。

    用一个数据结构

    struct wyh1
    {
    int p , pnum;
    bool operator < (const wyh1 & x) const
    {
    if(pnum != x.pnum) return pnum < x.pnum;
    return p < x.p;
    }
    }w[M];

    p是编号,也就是处于询问中的第几个,pnum就是这个询问访问的页面编号。

    重载小于符号,根据pnum的大小排序,如果pnum相同的话根据p来

    然后调用sort函数。再弄一个数组a,a[i]代表编号为i的询问离散化后的值。

    再维护一个at,at[num]表示离散化后为num值的页面是否在实际内存空间中存储。

    维护一个times数组,代表临时访问某个页面的次数。

    然后用一个堆维护当前最少访问次数并且进入最早的页面是哪一个。

    struct wyh
    {
    int ti , num , t;
    bool operator < (const wyh & x) const
    {
    if(ti != x.ti) return ti > x.ti;
    return t > x.t;
    }
    };

    ti代表这个页面的访问次数,num。。。可以无视。。t代表加入时间。

    priority_queue <wyh> q; 声明一个堆

    还得考虑的一个问题就是如何更新堆中维护的那些页面的访问次数,首先就是暴力,暴力的一个个拉出来更新再加入,虽然慢但是还是可以过的,因为时间限制是5秒一个。

    但是愚蠢的我写完这个之后还去想了一个用全局访问次数来维护,但是这样是不可以的,因为堆不支持这样,你更新的是全局,但是不会更新堆里的数据。

    亏我还因此纠结了好久,果然还是太弱了,哎。。

    具体怎么写呢?

    O(m)先扫一遍吧,获取到a[i]的值,然后判断at[a[i]]是否为1,为1 的话自然就是在实际内存中,那么就查询成功了,ans + 1,然后还得更新一下 times[a[i]]的内容,这个

    times我为什么叫临时的呢?因为你一个堆,不可能时时刻刻都去更改里面的内容,所以用一个times数组存到全局里面,到时候一次性更新上去就可以了。

    如果说at[a[i]]不为1,首先就判断堆中元素的个数如果小于n说明有空页面,直接插入到堆里面就可以了,关键是对于等于n的情况。

    现在我们不能够单纯的用堆顶的元素去替换对吧,因为times还没有更新上去,无法判断哪个页面的访问次数最少并且加入最早。

    我们先得更新这个堆中的内容。每次获取堆顶元素并且将times更新到ti上面去然后将times赋值为0。这就是为什么times叫做临时访问次数的原因了。

    每次更新完又将这个元素加入到堆里,一起维护,如果说times[a[p.t]]为0(为什么呢,为0代表他已经更新过一次了,更新了一次之后他又出现在了堆顶),那么代表之后也都没有内容了,所以当前的堆顶元素是符合我们条件的。

    所以就替换这个页面,然后就可以了。

  • 相关阅读:
    语句结构1练习
    语句结构(1)
    常用dos命令(4)
    常用dos命令(3)
    常用dos命令(2)
    常用dos命令(1)
    因式分解 · Factor Combinations
    电话号码的字母组合 · Letter Combinations of a Phone Number
    286 walls and gate最近的出口
    286被围绕的区域 · Surrounded Regions
  • 原文地址:https://www.cnblogs.com/lalawu/p/3554393.html
Copyright © 2020-2023  润新知