// Quicksort using Djikstra's 3-way partition.
 
#include <functional>
#include <algorithm>
#include <random>
#include <chrono>
#include <iostream>
using namespace std;
 
int randint(int a, int b)
{
    thread_local default_random_engine re(random_device{}());
    uniform_int_distribution<> pick(a, b);
    return pick(re);
}
 
void timeit(function<void()> thunk)
{
    using clock = chrono::steady_clock;
    clock::time_point t = clock::now();
    thunk();
    chrono::duration<double> elapsed = clock::now() - t;
    cout << "Elapsed: " << fixed << elapsed.count() << "s\n";
}
 
template<typename In>
ostream& ostream_join(ostream& os, In first, In last, string sep)
{
    if (first != last)
    {
        for (;;)
        {
            os << *first;
            if (++first == last) break;
            os << sep;
        }
    }
    return os;
}
 
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& a)
{
    os << '[';
    ostream_join(os, a.begin(), a.end(), ", ");
    os << ']';
    return os;
}
 
// Sort.
 
template<typename Bi, typename Compare, typename T>
pair<Bi, Bi> partition3(Bi first, Bi last, Compare comp, T pivot)
{
    for (Bi i = first; i != last;)
    {
        if (comp(*i, pivot))
        {
            iter_swap(first++, i++);
        }
        else if (comp(pivot, *i))
        {
            iter_swap(i, --last);
        }
        else
        {
            i++;
        }
    }
    return {first, last};
}
 
template<typename Ran, typename Compare>
void quicksort(Ran first, Ran last, Compare comp)
{
    if (auto n = distance(first, last); n >= 2)
    {
        auto eq = partition3(first, last, comp, *next(first, randint(0, n-1)));
        quicksort(first, eq.first, comp);
        quicksort(eq.second, last, comp);
    }
}
 
template<typename Ran>
void quicksort(Ran first, Ran last)
{
    quicksort(first, last, less<typename iterator_traits<Ran>::value_type>());
}
 
// Main.
 
void test1(int n)
{
    vector<int> t(n);
    generate(t.begin(), t.end(), bind(randint, 1-n, n-1));
    vector<int> u = t;
    sort(u.begin(), u.end());
    vector<int> v = t;
    quicksort(v.begin(), v.end());
    if (u == v)
    {
        cout << "Pass: " << n << endl;
    }
    else
    {
        cout << "Fail: " << n << endl;
        for (auto x : {t, u, v})
            cout << x << endl;
    }
}
 
void time1(int n)
{
    vector<int> t(n);
    generate(t.begin(), t.end(), bind(randint, 1-n, n-1));
    timeit([&]{
        quicksort(t.begin(), t.end());
    });
}
 
void p2call(int j, int k, function<void(int)> f)
{
    int m = 1;
    for (int i = 0; i < j; i++)
        m *= 2;
    for (int i = j; i < k; i++)
    {
        f(m-1);
        m *= 2;
    }
}
 
int main()
{
    p2call(0, 6, test1);
    p2call(16, 22, time1);
}
				Ly8gUXVpY2tzb3J0IHVzaW5nIERqaWtzdHJhJ3MgMy13YXkgcGFydGl0aW9uLgoKI2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDxyYW5kb20+CiNpbmNsdWRlIDxjaHJvbm8+CiNpbmNsdWRlIDxpb3N0cmVhbT4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCmludCByYW5kaW50KGludCBhLCBpbnQgYikKewogICAgdGhyZWFkX2xvY2FsIGRlZmF1bHRfcmFuZG9tX2VuZ2luZSByZShyYW5kb21fZGV2aWNle30oKSk7CiAgICB1bmlmb3JtX2ludF9kaXN0cmlidXRpb248PiBwaWNrKGEsIGIpOwogICAgcmV0dXJuIHBpY2socmUpOwp9Cgp2b2lkIHRpbWVpdChmdW5jdGlvbjx2b2lkKCk+IHRodW5rKQp7CiAgICB1c2luZyBjbG9jayA9IGNocm9ubzo6c3RlYWR5X2Nsb2NrOwogICAgY2xvY2s6OnRpbWVfcG9pbnQgdCA9IGNsb2NrOjpub3coKTsKICAgIHRodW5rKCk7CiAgICBjaHJvbm86OmR1cmF0aW9uPGRvdWJsZT4gZWxhcHNlZCA9IGNsb2NrOjpub3coKSAtIHQ7CiAgICBjb3V0IDw8ICJFbGFwc2VkOiAiIDw8IGZpeGVkIDw8IGVsYXBzZWQuY291bnQoKSA8PCAic1xuIjsKfQoKdGVtcGxhdGU8dHlwZW5hbWUgSW4+Cm9zdHJlYW0mIG9zdHJlYW1fam9pbihvc3RyZWFtJiBvcywgSW4gZmlyc3QsIEluIGxhc3QsIHN0cmluZyBzZXApCnsKICAgIGlmIChmaXJzdCAhPSBsYXN0KQogICAgewogICAgICAgIGZvciAoOzspCiAgICAgICAgewogICAgICAgICAgICBvcyA8PCAqZmlyc3Q7CiAgICAgICAgICAgIGlmICgrK2ZpcnN0ID09IGxhc3QpIGJyZWFrOwogICAgICAgICAgICBvcyA8PCBzZXA7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIG9zOwp9Cgp0ZW1wbGF0ZTx0eXBlbmFtZSBUPgpvc3RyZWFtJiBvcGVyYXRvcjw8KG9zdHJlYW0mIG9zLCBjb25zdCB2ZWN0b3I8VD4mIGEpCnsKICAgIG9zIDw8ICdbJzsKICAgIG9zdHJlYW1fam9pbihvcywgYS5iZWdpbigpLCBhLmVuZCgpLCAiLCAiKTsKICAgIG9zIDw8ICddJzsKICAgIHJldHVybiBvczsKfQoKLy8gU29ydC4KCnRlbXBsYXRlPHR5cGVuYW1lIEJpLCB0eXBlbmFtZSBDb21wYXJlLCB0eXBlbmFtZSBUPgpwYWlyPEJpLCBCaT4gcGFydGl0aW9uMyhCaSBmaXJzdCwgQmkgbGFzdCwgQ29tcGFyZSBjb21wLCBUIHBpdm90KQp7CiAgICBmb3IgKEJpIGkgPSBmaXJzdDsgaSAhPSBsYXN0OykKICAgIHsKICAgICAgICBpZiAoY29tcCgqaSwgcGl2b3QpKQogICAgICAgIHsKICAgICAgICAgICAgaXRlcl9zd2FwKGZpcnN0KyssIGkrKyk7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKGNvbXAocGl2b3QsICppKSkKICAgICAgICB7CiAgICAgICAgICAgIGl0ZXJfc3dhcChpLCAtLWxhc3QpOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgICBpKys7CiAgICAgICAgfQogICAgfQogICAgcmV0dXJuIHtmaXJzdCwgbGFzdH07Cn0KCnRlbXBsYXRlPHR5cGVuYW1lIFJhbiwgdHlwZW5hbWUgQ29tcGFyZT4Kdm9pZCBxdWlja3NvcnQoUmFuIGZpcnN0LCBSYW4gbGFzdCwgQ29tcGFyZSBjb21wKQp7CiAgICBpZiAoYXV0byBuID0gZGlzdGFuY2UoZmlyc3QsIGxhc3QpOyBuID49IDIpCiAgICB7CiAgICAgICAgYXV0byBlcSA9IHBhcnRpdGlvbjMoZmlyc3QsIGxhc3QsIGNvbXAsICpuZXh0KGZpcnN0LCByYW5kaW50KDAsIG4tMSkpKTsKICAgICAgICBxdWlja3NvcnQoZmlyc3QsIGVxLmZpcnN0LCBjb21wKTsKICAgICAgICBxdWlja3NvcnQoZXEuc2Vjb25kLCBsYXN0LCBjb21wKTsKICAgIH0KfQoKdGVtcGxhdGU8dHlwZW5hbWUgUmFuPgp2b2lkIHF1aWNrc29ydChSYW4gZmlyc3QsIFJhbiBsYXN0KQp7CiAgICBxdWlja3NvcnQoZmlyc3QsIGxhc3QsIGxlc3M8dHlwZW5hbWUgaXRlcmF0b3JfdHJhaXRzPFJhbj46OnZhbHVlX3R5cGU+KCkpOwp9CgovLyBNYWluLgoKdm9pZCB0ZXN0MShpbnQgbikKewogICAgdmVjdG9yPGludD4gdChuKTsKICAgIGdlbmVyYXRlKHQuYmVnaW4oKSwgdC5lbmQoKSwgYmluZChyYW5kaW50LCAxLW4sIG4tMSkpOwogICAgdmVjdG9yPGludD4gdSA9IHQ7CiAgICBzb3J0KHUuYmVnaW4oKSwgdS5lbmQoKSk7CiAgICB2ZWN0b3I8aW50PiB2ID0gdDsKICAgIHF1aWNrc29ydCh2LmJlZ2luKCksIHYuZW5kKCkpOwogICAgaWYgKHUgPT0gdikKICAgIHsKICAgICAgICBjb3V0IDw8ICJQYXNzOiAiIDw8IG4gPDwgZW5kbDsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBjb3V0IDw8ICJGYWlsOiAiIDw8IG4gPDwgZW5kbDsKICAgICAgICBmb3IgKGF1dG8geCA6IHt0LCB1LCB2fSkKICAgICAgICAgICAgY291dCA8PCB4IDw8IGVuZGw7CiAgICB9Cn0KCnZvaWQgdGltZTEoaW50IG4pCnsKICAgIHZlY3RvcjxpbnQ+IHQobik7CiAgICBnZW5lcmF0ZSh0LmJlZ2luKCksIHQuZW5kKCksIGJpbmQocmFuZGludCwgMS1uLCBuLTEpKTsKICAgIHRpbWVpdChbJl17CiAgICAgICAgcXVpY2tzb3J0KHQuYmVnaW4oKSwgdC5lbmQoKSk7CiAgICB9KTsKfQoKdm9pZCBwMmNhbGwoaW50IGosIGludCBrLCBmdW5jdGlvbjx2b2lkKGludCk+IGYpCnsKICAgIGludCBtID0gMTsKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgajsgaSsrKQogICAgICAgIG0gKj0gMjsKICAgIGZvciAoaW50IGkgPSBqOyBpIDwgazsgaSsrKQogICAgewogICAgICAgIGYobS0xKTsKICAgICAgICBtICo9IDI7CiAgICB9Cn0KCmludCBtYWluKCkKewogICAgcDJjYWxsKDAsIDYsIHRlc3QxKTsKICAgIHAyY2FsbCgxNiwgMjIsIHRpbWUxKTsKfQ==