Description
操作系统中一种重要的存储管理技术就是虚拟内存技术。操作系统中允许进程同时运行,也就是并行。每个进程都有其相对独立的数据块(进程运行的过程中将对其进行读写操作)。理想的情况下,这些数据块都应该存放在内存中,这样才能实现高效的读写操作。但事实上,内存的容量有限,每个进程只能把一部分数据放在内存中,为了解决这个矛盾,提出了虚拟内存技术。虚拟内存技术的基本原理是:对进程而言,内存空间是无限大的,进程可以随意地读写数据,而对操作系统内部而言,利用外存来模拟扩充的内存空间,进程要求访问某个内存单元时,交由操作系统处理,操作系统首先在内存中查找该单元是否存在,如果存在,查找成功,否则转入外存查找(一定存在于外存中)。就存储介质的物理性质而言,内存的访问速度相对于外存要快得多,因此对于每个进程来说操作系统应该把那些访问次数较多的数据存放在内存中,而把那些访问次数很少的数据放在外存中。如何选择内存中暂留的数据是一个很值得研究的问题,下面介绍一个内存管理中比较常用的算法:内存中的数据以页为基本存储单位,进程的读写操作都针对页来进行。实际内存空间被分割成n页,虚拟内存空间的页数往往要多得多。某一时刻,进程需要访问虚存编号为P的页,该算法的执行步骤如下: a. 首先在内存中查找,如果该页位于内存中,查找成功,转d,否则继续下面的操作; b. 寻找内存中是否存在空页(即没有装载任何数据页的页面),若有,则从外存中读入要查找页,并将该页送至内存中的空页进行存储,然后转d,否则继续下面的操作; c. 在内存中寻找一个访问次数最少的页面(如果存在多个页面的访问次数同时为最少,则选取最早读入数据进入内存的那个页面),从外存中读入要查找页,替换该页。 d. 结束所谓访问次数是指从当前页面进入内存到该时刻被访问的次数,如果该页面以前进入过内存并被其它页面替换,那么前面的访问次数不应计入这个时刻的访问次数中。你的任务是设计一个程序实现上述算法。测试数据将会提供m条读写内存的命令,每条命题提供要求访问的虚拟内存页的编号P。你的程序要求能够模拟整个m条命令的全部执行过程,所有的命令是按照输入的先后执行的,最开始的时候内存中的n页全为空。
Input
第1行为n<10000和m<1000000,分别表示内存页数和读写内存命令条数。接下来有m行,其中第i+1行有一个正整数Pi<=10^9,表示第i条读写内存命令需要访问的虚拟内存页的编号。
Output
仅包含一个正整数,表示在整个模拟过程中,在内存中直接查找成功的次数(即上面的算法只执行步骤a的次数)。
Sample Input
3 8
1
1
2
3
4
2
5
4
Sample Output
1
先离散化虚拟内存页,然后用堆来维护最小查询次数,又因为次数相同时还要比较时间,所以我们把次数乘以(m+1)再加上时间,就可以了
1 const 2 maxn=10010; 3 maxm=1000010; 4 var 5 n,m,tot,time,ans:longint; 6 q:array[0..maxn]of longint; 7 a,b,c,h:array[0..maxm]of longint; 8 flag:array[0..maxm]of int64; 9 10 procedure swap(var x,y:longint); 11 var 12 t:longint; 13 begin 14 t:=x;x:=y;y:=t; 15 end; 16 17 procedure sort(l,r:longint); 18 var 19 i,j,z:longint; 20 begin 21 i:=l; 22 j:=r; 23 z:=a[(l+r)>>1]; 24 repeat 25 while a[i]<z do 26 inc(i); 27 while a[j]>z do 28 dec(j); 29 if i<=j then 30 begin 31 swap(a[i],a[j]); 32 swap(b[i],b[j]); 33 inc(i); 34 dec(j); 35 end; 36 until i>j; 37 if i<r then sort(i,r); 38 if j>l then sort(l,j); 39 end; 40 41 procedure init; 42 var 43 i:longint; 44 begin 45 read(n,m); 46 for i:=1 to m do 47 begin 48 read(a[i]); 49 b[i]:=i; 50 end; 51 sort(1,m); 52 for i:=1 to m do 53 if a[i]<>a[i-1] then c[b[i]]:=i 54 else c[b[i]]:=c[b[i-1]]; 55 end; 56 57 procedure down(x:longint); 58 var 59 i:longint; 60 begin 61 i:=x<<1; 62 while i<=tot do 63 begin 64 if (flag[q[i+1]]<flag[q[i]])and(i<tot) then inc(i); 65 if flag[q[x]]>flag[q[i]] then 66 begin 67 swap(q[i],q[x]); 68 h[q[i]]:=i; 69 h[q[x]]:=x; 70 x:=i; 71 i:=x<<1; 72 end 73 else break; 74 end; 75 end; 76 77 procedure up(x:longint); 78 var 79 i:longint; 80 begin 81 while x>1 do 82 begin 83 i:=x>>1; 84 if flag[q[i]]>flag[q[x]] then 85 begin 86 swap(q[i],q[x]); 87 h[q[i]]:=i; 88 h[q[x]]:=x; 89 x:=i; 90 end 91 else break; 92 end; 93 end; 94 95 procedure insert(x:longint); 96 begin 97 inc(tot); 98 h[x]:=tot; 99 q[tot]:=x; 100 flag[x]:=time+m+1; 101 up(tot); 102 end; 103 104 procedure delete; 105 begin 106 flag[q[1]]:=0; 107 swap(q[1],q[tot]); 108 h[q[1]]:=1; 109 h[q[tot]]:=0; 110 dec(tot); 111 down(1); 112 end; 113 114 procedure work; 115 var 116 i,j:longint; 117 begin 118 for i:=1 to m do 119 begin 120 inc(time); 121 {for j:=1 to m do 122 write(flag[j],' '); 123 writeln; 124 for j:=1 to m do 125 write(h[j],' '); 126 writeln;} 127 if flag[c[i]]<>0 then 128 begin 129 inc(ans); 130 inc(flag[c[i]],m+1); 131 down(h[c[i]]); 132 end 133 else 134 if tot<n then insert(c[i]) 135 else 136 begin 137 delete; 138 insert(c[i]); 139 end; 140 end; 141 write(ans); 142 end; 143 144 begin 145 init; 146 work; 147 end.