模拟赛-列

题意

给你一个 \(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);
}

posted @ 2022-07-29 22:52  siriehn_nx  阅读(39)  评论(0编辑  收藏  举报