</>CodexBash
Back to problems
Not started

A cache that forgets what you have not used

Medium
3000 ms limit256 MB memoryDesignLinked listsHash maps

Stuck?

Show a hint

A hash map for finding, a doubly linked list for the order, and the map stores the node rather than the value so both are instant at once.

Build a cache holding at most capacity entries. Two operations arrive in order:

  • put key value stores a value. If the cache is full, the least recently used entry is thrown out first.
  • get key returns the stored value, or -1 if it is not there.

Both put and get count as using an entry, so either one moves it to the most-recently-used end. Report the answer to each get, in order.

Worked example#

Capacity 2:

operationcache after, oldest firstanswer
put 1 → 11
put 2 → 21 2
get 12 11
put 3 → 31 3(2 was oldest, thrown out)
get 21 3-1
put 4 → 43 4(1 was oldest, thrown out)
get 13 4-1
get 34 33
get 43 44

The idea#

Two requirements pull in different directions.

Finding a key must be instant. That is a hash map.

Knowing which entry is oldest must also be instant, and using an entry has to move it to the newest end without shifting anything else. A list would do it, but removing from the middle of an array is a walk.

The answer is to use both, pointing at each other:

  • a doubly linked list in use order, oldest at the front, newest at the back;
  • a hash map from key to the list node holding it.

Then get is: look the key up in the map to get the node, unlink it from wherever it is, and put it on the back. Unlinking is constant time because the node knows its own neighbours, which is exactly what a doubly linked list is for and why a singly linked one will not do.

Eviction is: take the node at the front, and remove its key from the map.

Why the map stores nodes, not values#

If it stored values, you could find the value fast and still have no idea where the entry sits in the order, so you would walk the list to find it. Storing the node is what makes both halves fast at once, and it is the trick worth taking away: two structures, each covering the other's weakness, joined by pointers.

About the input#

capacity, then the operations as a count and that many words, then a count and that many keys, then a count and that many values. A get still has a value in its slot; ignore it.

Constraints#

  • 1 <= capacity <= 3000
  • 1 <= operations <= 100000

Input

capacity, then operations as a count and that many words, then keys as a count and that many integers, then values the same way.

Output

A count is not printed. Print the answer to each get, separated by spaces.

Examples

Input

2
9
put put get put get put get get get
9
1 2 1 3 2 4 1 3 4
9
1 2 0 3 0 4 0 0 0

Output

1 -1 -1 3 4

Capacity two, so each put past the second throws out the least recently used.

Input

1
3
put put get
3
1 2 1
3
10 20 0

Output

-1

Capacity one: the second put evicts the first.

Input

2
2
get put
2
5 5
2
0 7

Output

-1

A get on an empty cache answers -1.

Something wrong with this problem? Report an issue

Ready to try it

Write your solution in C, C++, Java or Python and see every test case come back with the time and memory it took.

Free, and it stays free. No card.