luoguP3322 [SDOI2015] Sort

First, we can easily know the order of an arbitrary section of the exchange has no effect on the answer.

So we can search by the length of the interval.

And because the length of each interval can only be exchanged once, so we can be pruned.

For the length of the current search interval \ (X ^ 2 \) , we can for each length \ (2 ^ {x + 1 } \) interval, determine if it is monotonically increasing and the difference between two adjacent numbers \ (1 \) , if not, then marked mark.

If the interval is marked more than \ (2 \) , then in any case it can not be sorted, and directly back (think about it, why).

Here we divide the number of marker interval of discussion:

  • \ (0 \) ratings: directly next layer of search.

  • \ (1 \) a: direct section cut in half, the front and back exchange like.

    The reason is simple: on one section must meet the requirement that monotonically increasing and adjacent difference between the two numbers \ (1 \) , so long as the exchange before and after the two can (you can use mathematical induction idea).

  • \ (2 \) a: Consider two sections each head exchange, the exchange end to end, the first end of the exchange, the exchange tail end of the four cases, the search continues if possible.

We will take every possible answer to accumulate factorial \ (ans \) can be.

#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
const int O = 1 << 12 | 15;
template<class TT>
il TT read() {
    TT o = 0,fl = 1; char ch = getchar();
    while (!isdigit(ch) && ch != '-') ch = getchar();
    if (ch == '-') fl = -1, ch = getchar();
    while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
    return fl * o;
}
int n, a[O], anc[15][O], ans;
il void swapp(int & x, int & y) {x ^= y ^= x ^= y;}
il void Swap(int S1, int S2, int x) {
    for (int i = 0; i < 1 << x - 1; ++i)
        swapp(anc[x + 1][S1 + i], anc[x + 1][S2 + i]);
}
il void dfs(int, int);
il void Doit(int S1, int S2, int b1, int b2, int x, int num) {
    Swap(S1, S2, x);
    for (int i = 1; i < 1 << x; ++i) {
        if (anc[x + 1][b1 + i] - anc[x + 1][b1] != i) return Swap(S1, S2, x);
        if (anc[x + 1][b2 + i] - anc[x + 1][b2] != i) return Swap(S1, S2, x);
    }
    dfs(x + 1, num + 1);
    Swap(S1, S2, x);
}
il void dfs(int x, int num) {
    if (x == n + 1) {
        for (int i = 1; i <= 1 << n; ++i) if (anc[x][i] ^ i) return ;
        int res = 1;
        for (int j = 2; j <= num; ++j) res *= j;
        ans += res;
        return ;
    }
    int cnt = 0, S1, S2;
    for (int i = 1; i <= 1 << n; i += 1 << x)
        for (int j = 1; j < 1 << x; ++j)
            if (anc[x][i + j] != anc[x][i] + j) {
                if (cnt == 2) return ;
                if (cnt) S2 = i;
                else S1 = i;
                ++cnt; break;
            }
    for (int i = 1; i <= 1 << n; ++i) anc[x + 1][i] = anc[x][i];
    if (!cnt) return dfs(x + 1, num);
    if (cnt == 1) {
        Swap(S1, S1 + (1 << x - 1), x);
        dfs(x + 1, num + 1);
        return ;
    }
    Doit(S1, S2, S1, S2, x, num); Doit(S1 + (1 << x - 1), S2 + (1 << x - 1), S1, S2, x, num);
    Doit(S1, S2 + (1 << x - 1), S1, S2, x, num); Doit(S1 + (1 << x - 1), S2, S1, S2, x, num);
}
int main() {
    n = gi();
    for (int i = 1; i <= 1 << n; ++i) anc[1][i] = gi();
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/lylyl/p/11762225.html