# 银河

SKYIV STUDIO

博客园 :: 首页 :: :: :: :: :: 订阅 :: 管理 ::
 268 随笔 :: 2 文章 :: 2606 评论 :: 48 引用

### 公告

Timus 1037. Memory management 要求你实现一个内存管理器。

## 1037. Memory management

Time Limit: 2.0 second
Memory Limit: 16 MB

### Background

Don't you know that at school pupils’ programming contest a new computer language has been developed. We call it D++. Generally speaking it doesn't matter if you know about it or not. But to run programs written in D++ we need a new operating system. It should be rather powerful and complex. It should work fast and have a lot of possibilities. But all this should be done in a future.

And now you are to… No. You should not devise the name for the operating system. You are to write the first module for this new OS. And of course it's the memory management module. Let's discuss how it is expected to work.

### Problem

Our operating system is to allocate memory in pieces that we’ll call “blocks”. The blocks are to be numbered by integers from 1 up to N. When operating system needs more memory it makes a request to the memory management module. To process this request the memory management module should find free memory block with the least number. You may assume that there are enough blocks to process all requests.

Now we should define the meaning of words “free block”. At the moment of first request to the memory management module all blocks are considered to be free. Also a block becomes free when there were no requests to it during T minutes.

You may wonder about a notion “request to allocated blocks”. What does it mean, “request to allocated block”? The answer is simple: at any time the memory management module may be requested to access a given block. To process this request the memory management module should check if the requested block is really allocated. If it is, the request is considered to be successful and the block remains allocated for T minutes more. Otherwise the request is failed.

That's all about the algorithms of the memory management block. You are to implement them for N = 30 000 and T = 10 minutes.

### Input

Each line of input contains a request for memory block allocation or memory block access. Memory allocation request has a form:

<Time> +

where <Time> is a nonnegative integer number not greater than 65 000. Time is given in seconds. Memory block access request has a form:

<Time> . <BlockNo>

where <Time> meets conditions mentioned above for the memory allocation request and <BlockNo> is an integer value in range from 1 to N. There will be no more than 80000 requests.

### Output

For each line of input you should print exactly one line with a result of request processing. For memory allocation request you are to write an only integer — a number of allocated block. As it was mentioned above you may assume that every request can be satisfied, there will be no more than N simultaneously allocated blocks. For memory block access request you should print the only character:

• '+' if request is successful (i.e. block is really allocated);
• '-' if request fails (i.e. block with number given is free, so it can't be accessed).

Requests are arranged by their times in an increasing order. Requests with equal times should be processed as they appear in input.

### Sample

input output
1 +
1 +
1 +
2 . 2
2 . 3
3 . 30000
601 . 1
601 . 2
602 . 3
602 +
602 +
1202 . 2
1
2
3
+
+
-
-
+
-
1
3
-

Problem Author: Alexander Klepinin
Problem Source: Ural State University Internal Contest October'2000 Students Session

### 题意

<Time> +

<Time> . <BlockNo>

### 解题思路

struct Block
{
public int Id { get; private set; }
public int Time { get; set; }
public Block(int id, int time) : this() { Id = id; Time = time; }
}

sealed class TimeComparer : IComparer<Block>
{
public int Compare(Block x, Block y)
{
return (x.Time == y.Time) ? 0 : ((x.Time < y.Time) ? 1 : -1);
}
}

sealed class IdComparer : IComparer<int>
{
public int Compare(int x, int y)
{
return (x == y) ? 0 : ((x < y) ? 1 : -1);
}
}


using System;
using System.Collections.Generic;
using Skyiv.Util;

namespace Skyiv.Ben.Timus
{
// http://acm.timus.ru/problem.aspx?space=1&num=1037
sealed class T1037
{
static void Main()
{
const int T = 10 * 60, N = 30000;
var used = new KeyedPriorityQueue(new TimeComparer());
var free = new PriorityQueue<int>(new IdComparer());
for (var i = 1; i <= N; i++) free.Push(i);
for (string s; (s = Console.ReadLine()) != null; )
{
var ss = s.Split();
int id, time = int.Parse(ss[0]);
for (Block v; used.Count > 0 && (v = used.Top()).Time <= time; used.Pop()) free.Push(v.Id);
if (ss.Length == 2)
{
used.Push(new Block(id = free.Pop(), time + T));
Console.WriteLine(id);
}
else if (ss.Length == 3)
{
var hited = used.ContainsKey(id = int.Parse(ss[2]));
if (hited) used.Update(new Block(id, time + T));
Console.WriteLine(hited ? "+" : "-");
}
}
}
}
}


class KeyedPriorityQueue
{
Dictionary<int, int> keys;
IComparer<Block> comparer;
Block[] heap;

public int Count { get; private set; }

public KeyedPriorityQueue(IComparer<Block> comparer)
{
this.keys = new Dictionary<int, int>();
this.comparer = (comparer == null) ? Comparer<Block>.Default : comparer;
this.heap = new Block[16];
}

public bool ContainsKey(int id)
{
return keys.ContainsKey(id);
}

public void Update(Block v)
{
if (!ContainsKey(v.Id)) throw new ArgumentOutOfRangeException("v", v, "更新优先队列时无此健值");
var cmp = comparer.Compare(v, heap[keys[v.Id]]);
heap[keys[v.Id]].Time = v.Time;
if (cmp < 0) SiftDown(keys[v.Id]);
else if (cmp > 0) SiftUp(keys[v.Id]);
}

public void Push(Block v)
{
if (Count >= heap.Length) Array.Resize(ref heap, Count * 2);
heap[keys[v.Id] = Count++] = v;
SiftUp(keys[v.Id]);
}

public Block Pop()
{
var v = Top();
keys.Remove(v.Id);
heap[0] = heap[--Count];
if (Count > 0) SiftDown(keys[heap[0].Id] = 0);
return v;
}

public Block Top()
{
if (Count > 0) return heap[0];
throw new InvalidOperationException("优先队列为空");
}

void SiftUp(int n)
{
var v = heap[n];
for (var n2 = n / 2; n > 0 && comparer.Compare(v, heap[n2]) > 0; n = n2, n2 /= 2)
heap[keys[heap[n2].Id] = n] = heap[n2];
heap[keys[v.Id] = n] = v;
}

void SiftDown(int n)
{
var v = heap[n];
for (var n2 = n * 2; n2 < Count; n = n2, n2 *= 2)
{
if (n2 + 1 < Count && comparer.Compare(heap[n2 + 1], heap[n2]) > 0) n2++;
if (comparer.Compare(v, heap[n2]) >= 0) break;
heap[keys[heap[n2].Id] = n] = heap[n2];
}
heap[keys[v.Id] = n] = v;
}
}


KeyedPriorityQueue 用一个字典(Dictionary<int, int> keys)来存储“内存块”的编号(Id)及其在堆中的索引，以便判断给定的“内存块”是否在队列中(bool ContainsKey(int id))，并且根据需要更新其到期时间(Update(Block v))。

### 进一步的讨论

1. “内存块”的总数目 N 不超过 30,000
2. 时间 Time 不超过 65,000
3. 请求的总数不超过 80,000

for (var i = 1; i <= N; i++) free.Push(i);

sealed class MyPriorityQueue
{
int id = 1;
PriorityQueue<int> queue;

public MyPriorityQueue(IComparer<int> comparer)
{
queue = new PriorityQueue<int>(comparer);
}

public void Push(int v)
{
queue.Push(v);
}

public int Pop()
{
return (queue.Count == 0) ? id++ : queue.Pop();
}
}

posted on 2009-04-19 15:57 银河 阅读(...) 评论(...) 编辑 收藏