模拟赛-列
列
题意
给你一个 \(n\) 的排列,然后要求你用不超过 \(200\) 次操作把这个排列变得有序。
每一次操作是,你把这个序列编程若干段 \(D_1D_2\ldots D_k\),然后变成 \(D_k\ldots D_2 D_1\),之后把所有标号为奇数的段反转。
题解
有一个次数不超过 \(n+1\) 的方法,每次把序列分成三段,然后在 \([1:i - 1]\) 的段中可以加入一个 \(i\) 即可。
下面是操作次数 \(O(\log ^ 2n)\) 方法,考虑如果把序列按照大于 \(m\) 的变成 \(1\),小于等于 \(m\) 的变成 \(0\),那么怎么可以把这个序列变成 \(00001111\) 之类的。
继续按照区间分治,分界点为 \(mid\),区间两边都是 \(0001111\) 之类的,那么我们可以用一次操作来把这段变好。我们考虑可以把互不相交的段放在一次做,具体可以记录当前的次数即可。
// Siriqwq
#include <bits/stdc++.h>
using std::cin;
using std::cout;
using std::vector;
using std::copy;
using std::reverse;
using std::sort;
using std::get;
using std::unique;
using std::swap;
using std::array;
using std::cerr;
using std::function;
using std::map;
using std::set;
using std::pair;
using std::mt19937;
using std::make_pair;
using std::tuple;
using std::make_tuple;
using std::uniform_int_distribution;
using ll = long long;
namespace qwq {
mt19937 eng;
void init(int Seed) {return eng.seed(Seed);}
int rnd(int l = 1, int r = 1000000000) {return uniform_int_distribution<int> (l, r)(eng);}
}
template<typename T>
inline void chkmin(T &x, T y) {if (x > y) x = y;}
template<typename T>
inline void chkmax(T &x, T y) {if (x < y) x = y;}
template<typename T>
inline T min(const T &x, const T &y) {return x < y ? x : y;}
template<typename T>
inline T max(const T &x, const T &y) {return x > y ? x : y;}
char buf[100000], *bufs, *buft;
#define gc() ((bufs == buft && (buft = (bufs = buf) + fread(buf, 1, 100000, stdin))), bufs == buft ? -1 : *bufs++)
template<typename T>
inline void read(T &x) {
x = 0;
bool f = 0;
char ch = gc();
while (!isdigit(ch)) f = ch == '-', ch = gc();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
if (f) x = -x;
}
inline void reads(char *s) {
char ch = gc();
while (isspace(ch)) ch = gc();
while (!isspace(ch) && ch != EOF) *(s++) = ch, ch = gc();
*s = 0;
return;
}
template<typename T, typename ...Arg>
inline void read(T &x, Arg &... y) {
read(x);
read(y...);
}
#define O(x) cerr << #x << " : " << x << '\n'
const double Pi = acos(-1);
const int MAXN = 262144, MOD = 998244353, inv2 = (MOD + 1) / 2, I32_INF = 0x3f3f3f3f;
const long long I64_INF = 0x3f3f3f3f3f3f3f3f;
auto Ksm = [] (int x, int y) -> int {
if (y < 0) {
y %= MOD - 1;
y += MOD - 1;
}
int ret = 1;
for (; y; y /= 2, x = (long long) x * x % MOD) if (y & 1) ret = (long long) ret * x % MOD;
return ret;
};
auto Mod = [] (int x) -> int {
if (x >= MOD) return x - MOD;
else if (x < 0) return x + MOD;
else return x;
};
template<const int N_num, const int M_num>
struct Graph {
int H[N_num];
struct Edge {int to, lac;} e[M_num];
inline void add_edge(int x, int y) {e[*H] = {y, H[x]};H[x] = (*H)++;}
inline void init() {memset(H, -1, sizeof H);*H = 0;}
};
#define go(x, y) for (int i = x.H[y], v; (v = x.e[i].to) && ~i; i = x.e[i].lac)
inline int ls(int k) {return k << 1;}
inline int rs(int k) {return k << 1 | 1;}
using ull = unsigned long long;
void add(int &x, int y) {if ((x += y) >= MOD) x -= MOD;}
int N, M, A[MAXN];
vector<array<int, 2U>> p[MAXN];
vector<int> vk[MAXN];
inline void mfy(int d, int l, int r) {
if (l >= r) return;
reverse(A + l, A + 1 + r);
p[d].push_back({l, r});
}
int gao(int d, int l, int r, int md) {
if (l == r) return A[l] > md;
assert(d);
int mid = (l + r) / 2, u = gao(d - 1, l, mid, md), v = gao(d - 1, mid + 1, r, md);
if (!u || r - mid == v) return u + v;
mfy(d, mid - u + 1, r - v);
return u + v;
}
void dfs(int d, int l, int r) {
if (l == r) return;
// O(l);
int mid = (l + r) / 2, dt = ceil(log2(r - l + 1));
gao(d + dt - 1, l, r, mid);
dfs(d + dt, l, mid);
dfs(d + dt, mid + 1, r);
}
int main() {
freopen("cut.in", "r", stdin);
freopen("cut.out", "w", stdout);
// std::ios::sync_with_stdio(0);
// cout << std::fixed << std::setprecision(8);
// cin.tie(0);
// cout.tie(0);
qwq::init(20050112);
read(N, M);
for (int i = 1; i <= N; ++i) read(A[i]);
dfs(1, 1, N);
int k = 0;
for (int i = 1; i < 666; ++i) if (p[i].size()) {
++k;
int s = 0;
for (auto &j: p[i]) {
vk[k].push_back(j[0] - s - 1);
vk[k].push_back(j[1] - j[0] + 1);
s = j[1];
}
vk[k].push_back(N - s);
}
if (k & 1) vk[++k].push_back(N);
printf("%d\n", k);
for (int i = 1; i <= k; ++i) {
printf("%u ", vk[i].size());
if (!(i & 1)) reverse(vk[i].begin(), vk[i].end());
for (auto &j: vk[i]) printf("%d ", j);
putchar('\n');
}
// cout << (-3 / 2);
cerr << ((double) clock() / CLOCKS_PER_SEC) << '\n';
return (0-0);
}