However, even without these blocks the POW of #90 to #94 exceeds our current best and we should reorg to the new chain #90-94.
I wonder how bitcoin core (and the alternate implementations) handle this case.
It downloads the header chain first. Once it receives the new #90 to #100 headers, it will recognize the need for a re-org.
It the disconnects #100 back to #90, one at a time. This causes an update to the UTXO set. Each block is stored on the disk, but it also includes "undo" info that allows the disconnect to revert the changes made to the UTXO set by including that block.
Once it has disconnected #90, it will be back to the state from before that fork (#90 - #100) was used.
It then starts connecting the new #90 and onwards. Once it hits #95, the ConnectTip function will fail to connect the new block due to the double spend. This causes it to blacklist the block (RAM only, I think). This means that it will ignore those headers from that point onward. This prevents it switching over and back between forks.
If the new #94 has higher work than the old #100, it doesn't need to do anything more. That block is the longest chain. Miners will eventually extend that chain with an even newer #95. Normally though, #100 would have higher work than #95, unless the forks cross a difficulty adjustment.