Design a meeting-room scheduler that supports the following operations efficiently:
book(start, end) – given a half-open interval [start, end) representing a new meeting request, assign the meeting to the lowest-numbered available room. If no room is currently free, reject the request (return -1).
getLastNMeetings(n) – return the last n meetings that were successfully booked, in the order they were scheduled. Each entry should contain the room number and the interval [start, end).
cancel(meetingId) – cancel a previously booked meeting so that its room becomes available again for future bookings.
You may assume that the building has an unlimited number of rooms, but you must always use the smallest-numbered room that is free during the requested interval. All times are non-negative integers and a room can host at most one meeting at any moment.