~~~題面~~~
題解:首先我們要使得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命...