By request, here is the structure I found after I formulated the question:
The basic idea is to use a threaded Scapegoat tree along with a pointer to the minimum (and for good measure, the maximum as well). A simpler alternative to threading is maintaining predecessor and successor pointers in every node (which is equivalent, simpler, but has more overhead). I've come to call it a Scapegoat heap, just to give it some name.
Just this basic structure gives you these operations:
- Search: given a key, returns a pointer to the corresponding node in $\mathcal{O}(\log n)$ time.
- Insert: given a key, inserts the key into the structure, returning a pointer to that node in $\mathcal{O}(\log n)$ time.
- Predecessor/successor: given a pointer, returns the successor or predecessor in $\mathcal{O}(1)$ time.
- Get-Min/Max: returns the pointer to the minimum or maximum.
In the analysis of Scapegoat trees, the balancing overhead of deletion is analyzed as $\mathcal{O}(\log n)$, but the analysis actually gives a balance overhead of $\mathcal{O}(1)$ (which is ignored in the paper as they also count the $\mathcal{O}(\log n)$ time it takes to find the node that is to be deleted). So, if we have a pointer to a node, we can delete it in constant time (you can do this in threaded binary search tree in $\mathcal{O}(1)$ time) and combined with the $\mathcal{O}(1)$ overhead of balancing, this gives a $\mathcal{O}(1)$ time delete:
- Delete: given a pointer, deletes the node in $\mathcal{O}(1)$ time.
Combining this:
- Extract-Min/Max: deletes the minimum/maximum node in $\mathcal{O}(1)$ time.
You can do a bit more with pointers: for instance it's not hard to maintain a pointer to the median or some other order statistic, so you can maintain a constant number of such pointers if you need them.
Some other things:
- Construct: given $n$ keys in sorted order, build a Scapegoat heap in $\mathcal{O}(n)$ time.
- Balance: balance the tree so it forms a perfectly balanced binary search tree (reduces overhead of searching) in $\mathcal{O}(n)$ time (you can do this a constant factor faster than the paper suggests by the way, by making use of predecessor/successor pointers).
And finally, I'm pretty sure you can support these operations, but I need to think about these a bit more before knowing this for sure:
- Insert-New-Min/Max: given a key that is smaller/larger than any key already in the structure, inserts the key into the structure, returning a pointer to that node in $\mathcal{O}(1)$ time.