JSOI2010 快取交換 貪心 堆

2022-04-29 22:51:12 字數 1587 閱讀 2210

~~~題面~~~

題解:首先我們要使得miss的次數盡量少,也就是要盡量保證每個點在被訪問的時候,這個點已經存在於cache中。

那麼我們可以得到乙個結論:

如果cache已滿,那麼我們就從cache裡面取出下乙個出現位置最遠的那個數(如果不出現了那麼令下乙個出現位置為inf)

所以用堆維護即可。

我們記錄乙個next[i],表示s[i]後面再次遇到s[i]的位置是哪,如果當前的s[i]就是最後乙個s[i],那麼next[i] = inf

值得注意的是,遇到相同元素時我們並不需要從堆中刪除上乙個數然後再塞入當前數,因為這將不會對操作產生影響。而且要強行刪除的話要重建整個堆,時間複雜度承受不來。。。

為什麼不會有影響?

注意到對於相同元素而言,next[i]是遞增的

即next[i] < next[next[i]] < next[next[next[i]]] 

而遇到相同元素就代表遇到了next[i],所以塞入這個數後,上乙個數雖然沒有被刪除,但被這個數覆蓋了,每次取出肯定是優先這個數的

(為什麼突然覺得有點不太嚴謹。。。。那為了保險的話就在取數的時候判斷一下就好了)

1

//luogu-judger-enable-o2

2 #include3

using

namespace

std;

4#define r register int

5#define ac 100100

6#define inf 10000000

7int

n, m, tot, cnt, ans;

8int

s[ac], last[ac], w[ac], next[ac];

9bool

z[ac];

1011

struct

cmp16

};17

18 priority_queue, cmp>q;

1920 inline int

read()

2127

28 inline bool cmp(int a, int

b)29

3233

int half(int x)//

二分離散化後的編號

3443

return

l;44}45

46void

pre()47

60for(r i = 1; i <= n; i++)

61if(!next[i]) next[i] =inf;

62 }//

最後乙個的next為inf(最優先彈出)

6364

void

work()

65 //

因為不刪去舊元素並不會造成影響,因此還是可以視作q內沒有重複元素的

75else

if(cnt < m) //

如果還沒有滿

7681

else

8291

}92 printf("

%d\n

", ans);93}

9495

intmain()

96

JSOI2010 快取交換

考慮乙個貪心 就是每次我們都選擇佇列裡面之後最晚加入的元素彈出。維護乙個nxt陣列就行了。特判一下之後不會再加入的元素。如下 include include include include include include define maxn 200010 using namespace std ...

JSOI2010 快取交換

當遇到需要將主存單元加進cache的時候,就看cache裡是否滿了,滿了的話,就刪除離最靠後的那乙個,這樣一定最優。但是網上部落格的 太長了。其實只需要判斷一下當前的優先佇列的top是否仍在cache中即可。重題 poi2005 sam toy cars,ac數 2 include include ...

1826 JSOI2010 快取交換

在計算機中,cpu只能和快取記憶體cache直接交換資料。當所需的記憶體單元不在cache中時,則需要從主存裡把資料調入cache。此時,如果cache容量已滿,則必須先從中刪除乙個。例如,當前cache容量為3,且已經有編號為10和20的主存單元。此時,cpu訪問編號為10的主存單元,cache命...