Explanation
There's a ton of ways to solve this, but since you're probably here from the square root decomposition module, let's just go over that one. The official editorial does have some nice alternative solutions as well.
Subtask
Let's first try to solve the subtask and come up with an solution.
Let's try to construct the minimum possible ordering for each prefix of the array. We can do this with a strategy similar to insertion sort.
We can insert an element into the prefix by swapping it down to the left until it reaches position where because its impossible to keep swapping it. However, if , it is more optimal to swap it back to the right until it reaches a point where .
Full solution
We can speed this up with square root decomposition. We can split the array into blocks of size .
We know an element can pass completely through a block if and where and are the maximum and minimum elements of the block respectively. We can find the rightmost block that element cannot pass through which takes at most O() since we check every block.
We can insert this element into the square root block at its correct position by swapping it down to the left inside the block till it reaches a place where it can't be swapped down anymore. This also takes time because of the block size.
Now we need to swap it back towards the right until it reaches a point where which makes the array lexographically minimum. We can do this by finding the first block to the right of it that has it's by checking each block again in .
Notice that there is an edge case here where can never be swapped down to the left past another element that is greater than it because of the restriction of even thought the element is greater than . In this case, we can push into the next block and then apply the strategy of checking when the . We can check this by seeing that if after inserting into the block and swapping towards the left and right appropriately as described above, reaches the end of the block.
Now the problem arises that when we add enough elements, the size of a block could potentially be bigger than . To deal with this issue we can split the block into two smaller blocks (each half the size of the original block) and insert them into the list of blocks. Inserting into a vector in C++ or ArrayList in Java, is dependent on the size of the array which in our case which takes . We can prove that the amount of blocks is bounded to .
Processing each element of the array took time so the total time complexity is .
Implementation
Time Complexity:
C++
#include <bits/stdc++.h>using namespace std;int n, k;struct Block {int hi = -INT32_MAX;int lo = INT32_MAX;vector<int> vals;
Java
import java.io.*;import java.util.*;public class MinimizingHaybales {// sqrt(1e5) is roughly 300static final int BLOCK_SIZE = 300;static int k;public static class Block {public int hi, lo;
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!