cf1427 D. Unshuffling a Deck
题意:
给定一个排列。每次操作把数组分成段 \([1,r_1],[r_1+1,r_2],\cdots ,[r_k+1,n]\) ,然后所有段之间翻转,段内元素顺序不变。构造一种操作次数不大于 n 的方案使数组有序。
\(n\le 52\)
思路:
假设有一段是已经有序的,初始为空,在数组首或者数组尾。从1 到 n,每次往有序段中加一个数。如果有序段本来在数组首,操作后有序段会跑到数组尾,反之同理。这样操作 n 次后数组一定有序
初始有序段在数组首还是尾跟 n 的奇偶性有关
const signed N = 55;
int n, a[N], p[N]; vector<vector<int>> ans;
void work(vector<int> &ve) {
static int t[N];
int ed = n, idx = 0;
reverse(all(ve)); for(int len : ve) {
for(int i = ed-len+1; i <= ed; i++)
t[++idx] = a[i];
ed -= len;
}
memcpy(a, t, sizeof a);
for(int i = 1; i <= n; i++) p[a[i]] = i;
}
signed main() {
iofast;
cin >> n; for(int i = 1; i <= n; i++)
cin >> a[i], p[a[i]] = i;
if(n % 2) p[0] = n + 1; else p[0] = 0;
for(int i = 1, now = n%2; i <= n; i++, now ^= 1) {
vector<int> res;
for(int j = 1; j < i; j++) res.pb(1);
res.pb(abs(p[i]-p[i-1]));
if(i-1+abs(p[i]-p[i-1]) < n) res.pb(n-(i-1+abs(p[i]-p[i-1])));
if(res.size() == 1) continue; //题目规定这种不输出
if(now) reverse(all(res));
ans.pb(res);
work(res);
}
cout << ans.size() << endl;
for(vector<int> &res : ans) {
cout << res.size();
for(int i : res) cout << ' ' << i;
cout << endl;
}
}

浙公网安备 33010602011771号