1 条题解

  • 0
    @ 2026-9-26 11:58:46

    重新理解一下题意,这两种操作其实可以把一个位置的元素向前移动 11 或 22。

    那既然如此,我们便将每个值 ii 的位置移动到下标 ii 即可,如果相距超过 11 就移动两个位置,否则移动 11 个。

    for (int i = 1; i <= n - 2; i++) {//每次选择三个
    	int pos;
    	for (int j = i; j <= n; j++) {//由于按顺序排放,i的位置一定>=i
    		if (i == a[j]) {
    			pos = j;
    			break;
    		}
    	}
    	if (i == pos) continue;
    	while (pos - i >= 2) {
    		mov2(pos);//左移2
    		pos -= 2;
    	}
    	if (pos != i) mov1(pos);//左移1
    }
    

    但是这种情况由于要同时考虑三个下标,所以无法处理 n−1n-1 和 nn。怎么办,特殊判断一下即可。

    我们发现向前移动两个的话是不会改变其余位置的相对顺序的,但移动一个不一定。故如果第 nn 个位置的元素可以通过两个两个移动到自己的位置上的话,我们就认为该情况可行,计入答案。否则就是无解。

    换句话说,如果 nn 和 n−1n-1 不匹配,nn 还是奇数,就无解。

    最后再将 11 移到最前面。

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 2100;
    int n, a[N], st;
    vector<pair<int, int> > ans;
    void mov(int id) {//将id位置转换为开头
    	if (id == st) return ;
    	ans.push_back(make_pair((st - id + n) % n, 1));
    	st = id;
    }
    void mov1(int id) {//左移1
    	mov(id - 1);
    	ans.push_back(make_pair(2, 2));
    	swap(a[id - 1], a[id]);
    	swap(a[id + 1], a[id]);
    }
    void mov2(int id) {//左移2
    	mov(id - 2);
    	ans.push_back(make_pair(1, 2)) ;
    	swap(a[id - 1], a[id]);
    	swap(a[id - 2], a[id - 1]);
    }
    int main() {
    	scanf("%d", &n);
    	st = 1;//现在开头的位置
    	for (int i = 1; i <= n; i++) {
    		scanf("%d", &a[i]);
    	}
    	if (n == 1) {
    		printf("0");
    		return 0;
    	}
    	if (n == 2) {
    		if (a[1] < a[2]) {
    			printf("0");
    		} else {
    			printf("1\n1a");
    		}
    		return 0;
    	}
    	for (int i = 1; i <= n - 2; i++) {//每次选择三个 
    		int pos;
    		for (int j = i; j <= n; j++) {//由于按顺序排放,i的位置一定>=i
    			if (i == a[j]) {
    				pos = j;
    				break;
    			}
    		}
    		if (i == pos) continue;
    		while (pos - i >= 2) {
    			mov2(pos);//左移2
    			pos -= 2; 
    		}
    		if (pos != i) mov1(pos);//左移1
    	}
    	if (a[n - 1] == n) {
    		if (n & 1) {
    			printf("NIE DA SIE");
    			return 0;
    		}
    		int pos = n - 1;
    		while (pos != 1) {
    			mov2(pos);
    			pos -= 2;
    		}
    	}
    	int pos;
    	for (int i = 1; i <= n; i++) {
    		if (a[i] == 1) {
    			pos = i;
    			break;
    		}
    	}
    	mov(pos);
    	printf("%d\n", (int)ans.size());
    	for (auto v : ans) {
    		if (v.second == 1) {
    			printf("%da ", v.first);
    		} else {
    			printf("%db ", v.first);
    		}
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    3879
    时间
    400ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者