#include "testlib.h"
#include <bits/stdc++.h>
using namespace std;

struct segtree
{
    const int n;
    vector<int> val;

    segtree (const int n_) : n(n_), val(2 * n_) {}

    int get (int l, int r)
    {
        assert(0 <= l && l <= r && r <= n);
        int ans = 0;

        for (l += n, r += n; l < r; l >>= 1, r >>= 1)
        {
            if (l & 1)
                ans += val[l++];
            if (r & 1)
                ans += val[--r];
        }

        return ans;
    }

    void incr (int pos, const int delta)
    {
        assert(0 <= pos && pos < n);
        for (pos += n; pos > 0; pos >>= 1)
            val[pos] += delta;
    }
};

vector<int> get_a (const vector<int> &p)
{
    const int n = int(p.size());
    vector<int> where(n, -1);

    for (int i = 0; i < n; i++)
    {
        assert(0 <= p[i] && p[i] < n);
        where[p[i]] = i;
    }
    assert(count(where.begin(), where.end(), -1) == 0);

    segtree info(n);
    vector<int> a(n);

    for (int i = n - 1; i >= 0; i--)
    {
        a[i] = info.get(p[i] + 1, n);
        info.incr(p[i], +1);
    }

    return a;
}

int main (int argc, char *argv[])
{
    registerGen(argc, argv, 1);

    const int n = opt<int>("n");
    const string mode = opt<string>("mode");
    const bool noise = opt<bool>("noise");

    vector<int> a(n);

    if (mode == "direct")
    {
        const string type = opt<string>("dirtype");

        if (type == "min")
            fill(a.begin(), a.end(), 0);
        else if (type == "max")
        {
            for (int i = 0; i < n; i++)
                a[i] = n - i - 1;
        }
        else if (type == "random")
        {
            for (int i = 0; i < n; i++)
                a[i] = rnd.next(0, n - i - 1);
        }
    }
    else if (mode == "reverse")
    {
        vector<int> p(n, -1);

        const string type = opt<string>("revtype");
        const bool to_rev = opt<bool>("flip");
        const bool to_inv = opt<bool>("negate");

        if (type == "alternating")
        {
            int left = 0, right = n - 1;

            for (int i = 0; i < n; i++)
            {
                if (i % 2 == 0)
                    p[i] = left++;
                else
                    p[i] = right--;
            }
        }
        else if (type == "doublesided")
        {
            int left = 0;

            for (int i = 0; i <= n - 1 - i; i++)
            {
                p[i] = left++;
                if (i != n - 1 - i)
                    p[n - 1 - i] = left++;
            }
        }
        else if (type == "blocky")
        {
            const int cnt = int(sqrt(n));
            const int len = n / cnt;

            for (int i = 0; i < cnt; i++)
            {
                for (int j = 0; j < len; j++)
                    p[i * len + j] = (cnt - 1 - i) * len + j;
            }

            for (int i = cnt * len; i < n; i++)
                p[i] = i;
        }

        if (to_rev)
            reverse(p.begin(), p.end());
        if (to_inv)
        {
            for (auto &it : p)
                it = n - 1 - it;
        }

        a = get_a(p);
    }
    else
        assert(false);



    if (noise)
    {
        for (int i = 0; i < n; i++)
        {
            a[i] += rnd.next(-3, +3);
            a[i] = clamp(a[i], 0, n - 1 - i);
        }
    }

    for (int i = 0; i < n; i++)
        assert(0 <= a[i] && a[i] <= n - 1 - i);

    cout << n << endl;
    for (int i = 0; i < n; i++)
        cout << a[i] << " \n"[i + 1 == n];
}
