The most common models of small OLED displays (SSD1306, etc) have a (write-only) framebuffer in the display controller, and can be written to incrementally. If you structure your visual interface with certain simple constraints in mind, you can update it without using any additional dynamic memory.
That would probably be 100x more complicated than the actual business logic on a small microcontroller and there are limits to program memory for the "streaming this string to the screen by constantly computing if a given pixel is on one at a time" algorithm.
edit addendum;
If it was using a 7-segment display, it is either really cheap or really simple "a graphical GUI on a screen" IS NOT A REASONABLE NEXT STEP.
I think we have radically different expectations of a simple embedded system.
RP2040 should cost $0.70 in some quantity (https://www.digikey.com/en/products/detail/raspberry-pi/SC09...) and in low-quantity it's $1 from places like CanaKit. That's actually shockingly cheap for an ARM Cortex M0; I was assuming your ATmegas and PIC18s with a similar pin count (40, 48, 64) would be a bit cheaper, but they seem to be around $2-4 in similar low-production quantity. Power efficiency won't be anywhere near as good with the ARM part, but if you're making a battery-powered device, you might be able to use the extra dollar or so to make it rechargable, then people care a bit less if it eats batteries.
Power consumption on the RP2040 is quite poor, actually; there's much better parts to use if you care about that.
If you just want a really cheap ARM microcontroller, Puya has some parts like the PY32F002A in the <$0.10 range. Single core, lower Fmax, and fewer peripherals than the RP2040, but the price is hard to argue with.
> That would probably be 100x more complicated than the actual business logic on a small microcontroller
It really isn't. I've implemented simple UIs on SSD1306 displays, and it's very easy to work with. The hardware is specifically set up to optimize for rows of 8px tall text (or multiples of that with a bit more effort). Once you have row/column addresses set up, each byte you write to the display writes one 8px column of pixels to a row and moves the column pointer over by a pixel. Printing text is a matter of streaming a sequence of bytes to the display.