ArrayList to store stacks and a TreeSet to track non-full stacks.push(val), find the leftmost stack with available space using the TreeSet. If all stacks are full, create a new stack. Add val to the identified stack and update the TreeSet.pop(), find the rightmost non-empty stack. Remove and return the top plate from this stack. Update the ArrayList and TreeSet accordingly.popAtStack(index), check if the stack at index is non-empty. If so, remove and return the top plate, updating the TreeSet.ArrayList and their indices from the TreeSet.