内存分配
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 5110 | Accepted: 985 |
Description
内存是计算机重要的资源之一,程序运行的过程中必须对内存进行分配。
经典的内存分配过程是这样进行的:
1. 内存以内存单元为基本单位,每个内存单元用一个固定的整数作为标识,称为地址。地址从0开始连续排列,地址相邻的内存单元被认为是逻辑上连续的。我们把从地址i开始的s个连续的内存单元称为首地址为i长度为s的地址片。
2. 运行过程中有若干进程需要占用内存,对于每个进程有一个申请时刻T,需要内存单元数M及运行时间P。在运行时间P内(即T时刻开始,T+P时刻结束),这M个被占用的内存单元不能再被其他进程使用。
3、假设在T时刻有一个进程申请M个单元,且运行时间为P,则:
1. 若T时刻内存中存在长度为M的空闲地址片,则系统将这M个空闲单元分配给该进程。若存在多个长度为M个空闲地址片,则系统将首地址最小的那个空闲地址片分配给该进程。
2. 如果T时刻不存在长度为M的空闲地址片,则该进程被放入一个等待队列。对于处于等待队列队头的进程,只要在任一时刻,存在长度为M的空闲地址片,系统马上将该进程取出队列,并为它分配内存单元。注意,在进行内存分配处理过程中,处于等待队列队头的进程的处理优先级最高,队列中的其它进程不能先于队头进程被处理。
现在给出一系列描述进程的数据,请编写一程序模拟系统分配内存的过程。
经典的内存分配过程是这样进行的:
1. 内存以内存单元为基本单位,每个内存单元用一个固定的整数作为标识,称为地址。地址从0开始连续排列,地址相邻的内存单元被认为是逻辑上连续的。我们把从地址i开始的s个连续的内存单元称为首地址为i长度为s的地址片。
2. 运行过程中有若干进程需要占用内存,对于每个进程有一个申请时刻T,需要内存单元数M及运行时间P。在运行时间P内(即T时刻开始,T+P时刻结束),这M个被占用的内存单元不能再被其他进程使用。
3、假设在T时刻有一个进程申请M个单元,且运行时间为P,则:
1. 若T时刻内存中存在长度为M的空闲地址片,则系统将这M个空闲单元分配给该进程。若存在多个长度为M个空闲地址片,则系统将首地址最小的那个空闲地址片分配给该进程。
2. 如果T时刻不存在长度为M的空闲地址片,则该进程被放入一个等待队列。对于处于等待队列队头的进程,只要在任一时刻,存在长度为M的空闲地址片,系统马上将该进程取出队列,并为它分配内存单元。注意,在进行内存分配处理过程中,处于等待队列队头的进程的处理优先级最高,队列中的其它进程不能先于队头进程被处理。
现在给出一系列描述进程的数据,请编写一程序模拟系统分配内存的过程。
Input
第一行是一个数N,表示总内存单元数(即地址范围从0到N-1)。从第二行开始每行描述一个进程的三个整数T、M、P(M <= N)。最后一行用三个0表示结束。
数据已按T从小到大排序。
输入文件最多10000行,且所有数据都小于109。
输入文件中同一行相邻两项之间用一个或多个空格隔开。
数据已按T从小到大排序。
输入文件最多10000行,且所有数据都小于109。
输入文件中同一行相邻两项之间用一个或多个空格隔开。
Output
包括2行。
第一行是全部进程都运行完毕的时刻。
第二行是被放入过等待队列的进程总数。
第一行是全部进程都运行完毕的时刻。
第二行是被放入过等待队列的进程总数。
Sample Input
10 1 3 10 2 4 3 3 4 4 4 1 4 5 3 4 0 0 0
Sample Output
12 2
Hint
时 刻 T |
内存占用情况 |
进程事件 |
|||||||||||
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
进程A申请空间(M=3, P=10)<成功> |
|||
1 |
A |
||||||||||||
2 |
A |
B |
进程B申请空间(M=4, P=3)<成功> |
||||||||||
3 |
A |
B |
进程C申请空间(M=4, P=4)<失败进入等待队列> |
||||||||||
4 |
A |
B |
D |
进程D申请空间(M=1, P=4)<成功> |
|||||||||
5 |
A |
C |
D |
进程B结束,释放空间 进程C从等待队列取出,分配空间 进程E申请空间(M=3, P=4)<失败进入等待队列> |
|||||||||
6 |
A |
C |
D |
||||||||||
7 |
A |
C |
D |
||||||||||
8 |
A |
C |
E |
进程D结束,释放空间 进程E从等待队列取出,分配空间 |
|||||||||
9 |
A |
E |
进程C结束,释放空间 |
||||||||||
10 |
A |
E |
|||||||||||
11 |
E |
进程A结束,释放空间 |
|||||||||||
12 |
进程E结束,释放空间 |
Source
思路:用个链表存一下剩的内存块,按题意模拟即可。复杂度k*k(k是行数)。
1 #include <iostream> 2 #include <fstream> 3 #include <sstream> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <cmath> 7 #include <string> 8 #include <cstring> 9 #include <algorithm> 10 #include <queue> 11 #include <stack> 12 #include <vector> 13 #include <set> 14 #include <map> 15 #include <list> 16 #include <iomanip> 17 #include <cctype> 18 #include <cassert> 19 #include <bitset> 20 #include <ctime> 21 22 using namespace std; 23 24 #define pau system("pause") 25 #define ll long long 26 #define pii pair<int, int> 27 #define pb push_back 28 #define mp make_pair 29 #define clr(a, x) memset(a, x, sizeof(a)) 30 31 const double pi = acos(-1.0); 32 const int INF = 0x3f3f3f3f; 33 const int MOD = 1e9 + 7; 34 const double EPS = 1e-9; 35 36 /* 37 #include <ext/pb_ds/assoc_container.hpp> 38 #include <ext/pb_ds/tree_policy.hpp> 39 40 using namespace __gnu_pbds; 41 tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_lis_update> T; 42 */ 43 44 int n; 45 struct node { 46 int s, e; 47 node () {} 48 node (int s, int e) : s(s), e(e) {} 49 int l() { 50 return e - s + 1; 51 } 52 void output() { 53 printf("s = %d, e = %d ", s, e); 54 } 55 } lis[20015]; 56 struct Q1 { 57 int m, t, p; 58 Q1 () {} 59 Q1 (int m, int t, int p) : m(m), t(t), p(p) {} 60 bool operator < (const Q1 &q) const { 61 return t < q.t; 62 } 63 void output() { 64 printf("m = %d, t = %d, p = %d ", m, t, p); 65 } 66 } q[10015]; 67 struct Q2 { 68 int s, e; 69 ll t; 70 Q2 () {} 71 Q2 (int s, int e, ll t) : s(s), e(e), t(t) {} 72 bool operator > (const Q2 &q) const { 73 return t > q.t; 74 } 75 void output() { 76 printf("s = %d e = %d t = %lld ", s, e, t); 77 } 78 }; 79 priority_queue<Q2, vector<Q2>, greater<Q2> > que; 80 queue<Q1> que1; 81 void print_que() { 82 priority_queue<Q2, vector<Q2>, greater<Q2> > tque; 83 puts("que: "); 84 while (que.size()) { 85 Q2 qq = que.top(); que.pop(); 86 qq.output(); 87 tque.push(qq); 88 } 89 puts(""); 90 while (tque.size()) { 91 que.push(tque.top()), tque.pop(); 92 } 93 } 94 void print_que1() { 95 queue<Q1> tque1; 96 puts("que1: "); 97 while (que1.size()) { 98 Q1 qq = que1.front(); que1.pop(); 99 qq.output(); 100 tque1.push(qq); 101 } 102 puts(""); 103 while (tque1.size()) { 104 que1.push(tque1.front()), tque1.pop(); 105 } 106 } 107 int nex[20015], pre[20015], cnt_index; 108 void Insert(int p, int x) { 109 nex[x] = p, nex[pre[p]] = x; 110 pre[x] = pre[p], pre[p] = x; 111 } 112 void Erase(int x) { 113 nex[pre[x]] = nex[x]; 114 pre[nex[x]] = pre[x]; 115 } 116 void printList() { 117 for (int i = 0; i != 20000; i = nex[i]) { 118 printf("i = %d, ", i);lis[i].output(); 119 } 120 puts(""); 121 } 122 int main() { 123 scanf("%d", &n); 124 int index = 0, t, m, p; 125 while (scanf("%d%d%d", &t, &m, &p) && t + m + p) { 126 q[++index] = Q1(m, t, p); 127 } 128 //sort(q + 1, q + index + 1); 129 pre[20000] = 0, nex[0] = 20000; 130 lis[0] = node(-2, -3); 131 lis[++cnt_index] = node(0, n - 1); 132 Insert(20000, cnt_index); 133 lis[++cnt_index] = node(n + 2, n + 1); 134 Insert(20000, cnt_index); 135 ll ans1 = 0, ans2 = 0, cur_t = 0; 136 for (int i = 1; i <= index + 1; ++i) { 137 while (que.size() && (i == index + 1 || que.top().t <= q[i].t)) { 138 139 int flag = 1; 140 ll pre_t = -MOD; 141 while (que.size() && (flag || pre_t == que.top().t)) { 142 Q2 qq = que.top(); que.pop(); 143 flag = 0, pre_t = qq.t; 144 ans1 = max(ans1, qq.t); 145 cur_t = max(cur_t, qq.t); 146 int it = 0; 147 for (; it != 20000; it = nex[it]) { 148 if (qq.e < lis[it].s) { 149 int it1 = pre[it]; 150 if (lis[it1].e == qq.s - 1) { 151 qq.s = lis[it1].s; 152 Erase(it1); 153 } 154 if (lis[it].s == qq.e + 1) { 155 lis[it].s = qq.s; 156 } else { 157 lis[++cnt_index] = node(qq.s, qq.e); 158 Insert(it, cnt_index); 159 } 160 break; 161 } 162 } 163 } 164 165 while (que1.size()) { 166 int tflag = 0; 167 Q1 q1 = que1.front(); 168 int it = 0; 169 for (; it != 20000; it = nex[it]) { 170 if (q1.m <= lis[it].l()) { 171 que.push(Q2(lis[it].s, lis[it].s + q1.m - 1, cur_t + q1.p)); 172 if (q1.m < lis[it].l()) { 173 lis[it].s = lis[it].s + q1.m; 174 } else { 175 Erase(it); 176 } 177 que1.pop(); 178 tflag = 1; 179 break; 180 } 181 } 182 if (!tflag) break; 183 } 184 /*if (i == index + 1) { 185 printf("cur_t = %lld ", cur_t); 186 printList(); 187 print_que(); 188 print_que1(); 189 }*/ 190 } 191 192 //printList(); 193 if (i == index + 1) { 194 if (que.empty()) break; 195 --i; 196 continue; 197 } 198 199 cur_t = max(cur_t, (ll)q[i].t); 200 //if (!q[i].p) continue; 201 int it = 0; 202 int tflag = 0; 203 for (; it != 20000; it = nex[it]) { 204 if (q[i].m <= lis[it].l()) { 205 que.push(Q2(lis[it].s, lis[it].s + q[i].m - 1, cur_t + q[i].p)); 206 if (q[i].m < lis[it].l()) { 207 lis[it].s = lis[it].s + q[i].m; 208 } else { 209 Erase(it); 210 } 211 tflag = 1; 212 break; 213 } 214 } 215 if (!tflag) que1.push(q[i]), ++ans2; 216 //printf("i = %d, ans2 = %lld ", i, ans2); 217 //q[i].output(); 218 //printf("i = %d, cur_t = %lld ", i, cur_t); 219 //print_que(); print_que1(); 220 //pau; 221 } 222 223 printf("%lld %lld", ans1, ans2); 224 return 0; 225 } 226 /* 227 8 228 2 1 1 229 2 1 1 230 3 7 2 231 3 7 2 232 3 2 2 233 5 3 2 234 5 2 2 235 6 4 2 236 6 6 2 237 6 1 2 238 6 8 1 239 7 1 2 240 7 2 2 241 8 3 1 242 8 1 2 243 8 1 2 244 9 1 1 245 9 2 2 246 9 1 2 247 10 7 2 248 0 0 0 249 */