TargetConstructionExists iff
LIS , LDS increasing blocks, each block decreasing, one block of size
exactly inversions (lexicographically smallest)greedy: at each position take the smallest value that keeps reachable
no two adjacent values consecutiveall evens, then all odds or
all adjacent differences distinctzigzag always
derangementrotate by one: ,
or conditionspair with its complement inside a block of size depends on the condition
given cycle typewrite the cycles consecutivelyalways
involution with fixed pointsswap disjoint pairs

LIS and LDS

vector<int> lisLdsPerm(int n, int a, int b) {  // LIS = a, LDS = b; empty if impossible
    if (a < 1 || b < 1 || a > n || b > n || a + b - 1 > n || (long long)a * b < n) return {};
    vector<int> sizes(a, 1); sizes[0] = b; int rest = n - b - (a - 1);
    for (int i = 1; i < a && rest > 0; i++) { int add = min(rest, b - 1); sizes[i] += add; rest -= add; }
    vector<int> p; int v = 0;
    for (int s : sizes) { for (int j = s; j >= 1; j--) p.push_back(v + j); v += s; }   // blocks decreasing inside, increasing across
    return p;
}

Exactly k inversions

vector<int> permWithInversions(int n, long long k) {   // exactly k inversions, 0 <= k <= n(n-1)/2
    vector<int> p; deque<int> rest;                    // place values n, n-1, ..., 1: value v can create up to v-1 inversions
    vector<int> pos;                                   // build by inserting: the largest value first
    for (int v = 1; v <= n; v++) rest.push_back(v);
    for (int i = 0; i < n; i++) {                      // position i: choose the smallest remaining value that keeps k reachable
        long long m = sz(rest) - 1;                    // the remaining suffix can still produce at most m(m-1)/2
        long long take = max(0LL, k - m * (m - 1) / 2);  // inversions this element must create (with smaller later ones)
        p.push_back(rest[take]); rest.erase(rest.begin() + take); k -= take;
    }
    return p;
}

No adjacent consecutive values

vector<int> noAdjacentConsecutive(int n) {     // |p[i+1] - p[i]| != 1; impossible for n = 2, 3
    if (n == 2 || n == 3) return {};
    vector<int> p;
    for (int v = 2; v <= n; v += 2) p.push_back(v);
    for (int v = 1; v <= n; v += 2) p.push_back(v);
    return p;
}

Related: Counting Fundamentals, Sequence DP (LIS).