2011-06-16 17:53:26Morris
a068. E. 看動畫 加强版
內容 :
小
米很喜歡看動畫,他會把看過的動畫都存到硬碟裡,這樣以後才可以再翻出來複習。但是因為他實在是有太多動畫了,一顆硬碟擺不下,所以他買了很多顆硬碟來
存。為了方便以後尋找,每一個硬碟都有一個編號,還有上面存了哪些動畫,動畫是以集為單位,一部動畫可能有很多集,但是一集一定會放在同一顆硬碟不會分在
兩顆。
有一天,當他想要把 OOXX 重看一遍時,發現一個麻煩的問題,動畫當然就是要從第一集開始一集集依序看完,但是不同集的動畫不一定放在同一個硬碟裡,因此要看完一部動畫可能會用到很 多顆硬碟。硬碟當然是要接上電腦才能用,但是電腦的 USB 接頭是有限的,因此可能沒有辦法一次把全部的硬碟接上去,所以當你看完一集時可能需要抽換硬碟才能看到下一集。當然如果現在連在電腦上的硬碟已經有你要看 的那一集那就可以不用換。因為一直換硬碟實在是太麻煩了,會影響看動畫的心情。所以他把他想看的動畫存在哪一顆硬碟中依序跟你講,希望請你寫一個程式來決 定怎麼抽換硬碟才能使抽換次數降到最低。
舉例來說,動畫可能依序放在 5 4 3 2 1 這五個硬碟中,電腦上有三個 USB 接頭,最少需要兩次抽換才能看完整部動畫。方法如下,首先先把 5 4 3 接上電腦,之後把 5 4 拔掉換成 2 1,這樣就可以全部看完。
有一天,當他想要把 OOXX 重看一遍時,發現一個麻煩的問題,動畫當然就是要從第一集開始一集集依序看完,但是不同集的動畫不一定放在同一個硬碟裡,因此要看完一部動畫可能會用到很 多顆硬碟。硬碟當然是要接上電腦才能用,但是電腦的 USB 接頭是有限的,因此可能沒有辦法一次把全部的硬碟接上去,所以當你看完一集時可能需要抽換硬碟才能看到下一集。當然如果現在連在電腦上的硬碟已經有你要看 的那一集那就可以不用換。因為一直換硬碟實在是太麻煩了,會影響看動畫的心情。所以他把他想看的動畫存在哪一顆硬碟中依序跟你講,希望請你寫一個程式來決 定怎麼抽換硬碟才能使抽換次數降到最低。
舉例來說,動畫可能依序放在 5 4 3 2 1 這五個硬碟中,電腦上有三個 USB 接頭,最少需要兩次抽換才能看完整部動畫。方法如下,首先先把 5 4 3 接上電腦,之後把 5 4 拔掉換成 2 1,這樣就可以全部看完。
輸入說明
:
第一行有一個整數代表總共有幾筆測試資料。
每一筆測試資料有兩行。
第一行有 N, M 兩個整數,N 代表動畫總共有幾集,M 代表有幾個 USB 接頭。
第二行有 N 個整數 A1 到 AN,代表依序要使用的硬碟編號。
N ≤ 1000000, M ≤ 10000, 0 ≤ An ≤ 100000, 0 < T < 10
http://zerojudge.tw/ShowProblem?problemid=a068
輸出說明
:
每一筆測試資料輸出一個整數,代表最少要抽換多少次硬碟。
範例輸入 :
2 5 5 1 2 3 4 5 5 3 5 4 3 2 1
範例輸出 :
0 2
提示
:
NPSC d592: E. 看動畫 加强版
出處
:
NPSC 加强
(管理:liouzhou_101)
作法 : greedy
若槽上已滿,選擇插槽上下次使用最遠的拔除
作法必須很快,搜尋不能用O(N)
必須用O(1)的heap 找極值,修改O(logN)
因此普通的heap 行不通,也不是不行,記憶體會很大
因此寫個映射,來做修改
詳細 :
http://hi.baidu.com/prayan1988/blog/item/b7f68f39ba3288f8b311c74c.html
可以用來優化 最短路徑演算法,大致上就是這樣
作法 : greedy
若槽上已滿,選擇插槽上下次使用最遠的拔除
作法必須很快,搜尋不能用O(N)
必須用O(1)的heap 找極值,修改O(logN)
因此普通的heap 行不通,也不是不行,記憶體會很大
因此寫個映射,來做修改
詳細 :
http://hi.baidu.com/prayan1988/blog/item/b7f68f39ba3288f8b311c74c.html
可以用來優化 最短路徑演算法,大致上就是這樣
/**********************************************************************************/
/* Problem: a068 "E. 看動畫 加强版" from NPSC 加强 */
/* Language: C */
/* Result: AC (968ms, 9032KB) on ZeroJudge */
/* Author: morris1028 at 2011-06-16 09:45:20 */
/**********************************************************************************/
#include<stdio.h>
int next[1000001], pre[100001];
int A[1000001], L, set[100001];
char USB[100001];
struct Heap {
int x, node;
}Heap[10001];/*max heap*/
void Swap(int P, int S) {
int T;
T=Heap[P].x, Heap[P].x=Heap[S].x, Heap[S].x=T;
T=Heap[P].node, Heap[P].node=Heap[S].node, Heap[S].node=T;
set[Heap[S].node] = S, set[Heap[P].node] = P;
}
void siftup (int site) {
int S = site, P = site >> 1;
while(S >= 2 && Heap[P].x < Heap[S].x)
Swap(P, S), S = P, P = S >> 1;
}
void siftdown(int site) {
int P = site, S = site << 1;
while(S <= L) {
if(S < L && Heap[S+1].x > Heap[S].x) S++;
if(Heap[P].x >= Heap[S].x) break;
Swap(P, S), P = S, S = P << 1;
}
}
void ins(int site, int value, int t) {/*insert new node*/
Heap[site].node = value;
Heap[site].x = next[t];
set[value] = site, USB[value] = 1;
siftup(site);
}
void del() {/*delete last node*/
Swap(1, L), L--;
siftdown(1);
}
int Input() {
char cha;
unsigned int x = 0;
while(cha = getchar())
if(cha != ' ' && cha != '\n') break;
x = cha-48;
while(cha = getchar()) {
if(cha == ' ' || cha == '\n') break;
x = x*10 + cha-48;
}
return x;
}
main() {
int t, n, m;
scanf("%d", &t);
while(t--) {
scanf("%d %d", &n, &m);
int a, Ans = 0;
for(a = 0, L = 0; a < 100001; a++) /*initiate*/
pre[a] = 0, USB[a] = 0;
for(a = 1; a <= n; a++) {
A[a] = Input();
if(pre[A[a]])
next[pre[A[a]]] = a;
pre[A[a]] = a;
}
for(a = 0; a < 100001; a++)
if(pre[a])
next[pre[a]] = n+1;
for(a = 1; a <= n; a++) {
if(USB[A[a]]) {/*heap->p (next adjust)*/
Heap[set[A[a]]].x = next[a];
siftup(set[A[a]]);
continue;
}
if(L == m) {/*pull out*/
Ans++;
USB[Heap[1].node] = 0;/*max pull out*/
del();
}
L++, ins(L, A[a], a);
}
printf("%d\n", Ans);
}
return 0;
}