Here's the solution:
function solve(s, queries)
// Build implicit treap from string
root := null
for i from 0 to length(s) - 1
root := merge(root, createNode(s[i], randomPriority()))
for each (l, r) in queries
// 0-indexed: move [l-1, r-1] to front
(left, temp) := splitBySize(root, l - 1)
(mid, right) := splitBySize(temp, r - l + 1)
root := merge(merge(mid, left), right)
// Output final string via in-order traversal
printInOrder(root)
Time: . Space: .