Is it yet another range query for $$$O(log N)$$$? RSQ, RMQ, average, reversal on subsegment and even... next_permutation? Yes, of course! This problem an be solved using a simple and very old Narayana's algorithm. This algorithm invented by Indian mathematician Pandit Narayana more than 600 years ago.
Given array $$$a$$$. How to go to its next permutation?
Find the longest non-increasing suffix of the array (LNIS). If whole array is non-increasing, permutations are exhausted.
Let LNIS be a suffix $$$k$$$, where $$$k$$$ is position where it begins. Swap previous element, $$$a_{k-1}$$$ and the next largest number (NLN) that exists in suffix $$$k$$$.
Reverse suffix $$$k$$$.
This operations can be performed on a treap! Reversal is known, and swapping is just a combination of split and merge operations. Also we need to find LNIS and NLN. LNIS is sorted by definition, so we can apply binary search in order to find NLN of $$$a_{k-1}$$$.
But to find LNIS is more difficult. Let in each subtree maintain if the elements in this tree are non-increasing. Then recursion on the treap selects at most one subtree each step and find LNIS for $$$O(log N)$$$.
How to maintain this flag? Elements of a tree are non-increasing if and only if both subtrees are with non-increasing elements and last element of left subtree $$$\geq$$$ value of tree's root $$$\geq$$$ first element of right subtree. Empty subtrees don't affect the non-increasing order. Since we need to reverse segments, we should to maintain also a flag of non-decreasing order. These two flags are swapping while reversing.
The Code
void next_p(int L, int R, treap t=root){
treap l, r, swap1, swap2, between;
split(t, t, r, R+1, 0);
int k = find_k(t, R)+1;
split(t, l, t, max(L,k), 0);
t->reversed ^= 1;
if(k>L) {
split(l, l, swap1, k-1, 0);
int nln = find_nln(t, swap1->val, k);
//pr(nln);
split(t, between, t, nln, k); split(t, swap2, t, nln+1, nln);
merge(t, swap1, t); merge(t, between, t); merge(t, swap2, t);
}
merge(t, l, t); merge(t, t, r);
}