1. 程式人生 > >【貪心】【JSOI2010】快取交換

【貪心】【JSOI2010】快取交換

   快取交換

問題描述

在計算機中,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缺失次數

輸   入

輸入檔案第一行包含兩個整數N和M(1<=M<=N<=100,000),分別代表了主存訪問的次數和Cache的容量。

第二行包含了N個空格分開的正整數,按訪問請求先後順序給出了每個主存塊的編號(不超過1,000,000,000)。

輸    出

輸出一行,為Cache缺失次數的最小值。

樣  例

輸入資料

輸出資料

解釋

6 2

1 2 3 1 2 3

4

在第4次缺失時將3號單元換出Cache。

10 3

1 3 4 2 5 3 1 4 5 6

7

【思路】貪心,用next[i]陣列儲存第I個記憶體地址的下一次出現的位置,維護一個大根堆(我用優先佇列實現= =剛好今天剛學)

                要被換掉的這個數下一次出現的位置一定是越遠越優

               於是得到以下策略:

                如果當前命中,就把容器容量+1,push進當前點的next[i]值//因為優先佇列沒辦法找到當前值在佇列中的位置= =想出了這種奇葩的方法,居然過了ORZ,正確性好像不大能保證

               如果容器容量有剩餘,直接push進去

               如果需要交換出cache,彈出堆頂元素,並把當前點push進去

               mark陣列標記當前值是否在堆中

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
int n,m,f[100000],next[100000],last[10000000],mark[10000000],i,ans;

typedef pair<int,int> ele;



int main()
{
   // freopen("swap.in","r",stdin);
   // freopen("swap.out","w",stdout);
    scanf("%d%d",&n,&m);
    memset(mark,0,sizeof(mark));
    memset(next,1,sizeof(next));
    for (i=1;i<=n;i++){
        scanf("%d",&f[i]);
        next[last[f[i]]]=i;
        last[f[i]]=i;
        }
    priority_queue<ele> q;
    for (i=1;i<=n;i++){
       if (mark[f[i]]) { q.push(make_pair(next[i],f[i])); m++; continue;}
       if (q.size()<m)
           { q.push(make_pair(next[i],f[i])); ans++; mark[f[i]]=1; continue; }
       ele k=q.top();
       q.pop();
       mark[k.second]=0;
       q.push(make_pair(next[i],f[i]));
       mark[f[i]]=1;
       ans++;
    }
    printf("%d\n",ans);
   // getchar(); getchar();
}