Round 2’s problem B, “Minimum Sort”, is yet another twist on this year’s theme: sorting integers in convoluted ways.
In this instalment, we have two operations:
- swapping two elements, for free
- locating the minimum element of a contiguous range, for a cost inversely proportional to the range length.
I’ll be honest. I could only think of one natural way to sort using those two operations: selection sort. But that’s way too easy for a round 2 problem, isn’t it? So let’s rule it out using math.
Selection sort works like this:
- Identify the smallest element.
- Move it to the front.
- Recursively sort the elements after the front one.
So if \(L\) is the sequence’s length, the minimum operation is carried out for a cost of \(10^8\over L\). A free swap will bring it into place, then we repeat for the remaining \(L-1\)-element long sequence. It will take at most N iterations, so the total cost will be:
\[ \sum_{L=1}^N{10^8\over L} \le \left\lceil10^8 ln N\right\rceil \approx 4,6×10^8 \]
Unfortunately, we’re only allowed \(6×10^8\) coins, so we’re going to have to refine a bit.
Wait, what?
We’ve got enough coins. It’ll pass.
import Control.Monad
import System.Exit
import System.IO
main :: IO ()
= do
main LineBuffering
hSetBuffering stdout <- map read . words <$> getLine
[t,n] $ do
replicateM_ t 1..n-1] $ \i -> do
forM_ [$ "M " ++ show i ++ " " ++ show n
send <- get
m > i) $ do
when (m $ "S " ++ show i ++ " " ++ show m
send 1 <- get
pure ()
"D"
send 1 <- get
pure ()
send :: String -> IO ()
= putStrLn
send
get :: IO Int
= do
get <- readLn
n < 0) exitSuccess
when (n pure n
That was easy. Too easy. More on that later.
The full code is above, but it’s also on my GitHub if really you like the syntax highlighting there better for some reason.
See you soon for problem B!