LOJ #2158. 「POI2011 R1」移方块 Shift(构造)

题目

我太难了。
发现把第三个放到开头有点鬼畜。
我们来把这个操作规约到我们熟悉的操作。
做一次 A A B AAB
我们得到了什么?把 [ 2 , n ] [2,n] 每个数向后移两个位置。
所以我们可以从 i = [ 2 , n ] i=[2,n] 依次把 i i 移到 1 1 ,然后把 1.2.3.. i 1 1.2.3..i-1 这个之前已经排好序的序列用 A A B AAB 移到整个序列的最后,如果我们把 i 1 i-1 移到了 n 1 n-1 的位置,我们可以用 A B B ABB i 1 i-1 移到 n n
这个方法在 i < = n 2 i<=n-2 时都没有问题。
但是在 i > n 2 i>n-2 A B B ABB 就行不通了。
所以我们需要在这个时候特判,顺便判断无解。
读者自主完成不难。
A C   C o d e \mathrm{AC \ Code}

#include<bits/stdc++.h>
#define maxn 2005
#define rep(i,j,k) for(int i=(j);i<=(k);i++)
#define per(i,j,k) for(int i=(j);i>=(k);i--)
#define pii pair<int,int>
#define mp make_pair
#define pb emplace_back
using namespace std;

int n,a[maxn];
inline int find(int b){ rep(i,1,n) if(a[i]==b) return i; }
vector<pii >ans,a2;
inline void arg(int l,int r,int t){ static int b[maxn];
	rep(i,l,r) b[(i-l+t)%(r-l+1)+l]=a[i];
	rep(i,l,r) a[i]=b[i]; }
int main(){
	scanf("%d",&n);
	rep(i,1,n) scanf("%d",&a[i]);
	rep(i,2,n-2){
		int p=find(i);
		if(a[(p+n-2)%n+1]==i-1) continue;
		if(p^1)	ans.pb(mp(0,n+1-p)),arg(1,n,n+1-p);
		p=find(i-1);
		if(p^n){
			rep(j,1,(n-p)/2) ans.pb(mp(0,2)),ans.pb(mp(1,1));
			bool flg = 0;
			if((n-p)&1) ans.pb(mp(0,1)),ans.pb(mp(1,2)),flg=1;
			arg(2,n,n-p);
			if(flg)
				swap(a[2],a[3]);
		}
	}
	if(n&1){
		int p=find(n-1);
		if(a[(p+n-2)%n+1] ^ (n-2)){ puts("NIE DA SIE");return 0;}
	}
		int p=find(n);
		if(a[(p+n-2)%n+1]^(n-1)){
			if(p^1)	ans.pb(mp(0,n+1-p)),arg(1,n,n+1-p);
			p=find(n-1);
			if(p^n){
				rep(j,1,(n-p)/2) ans.pb(mp(0,2)),ans.pb(mp(1,1));
				arg(2,n,n-p);
			}
		}
		p=find(1);
		if(p^1) ans.pb(mp(0,n+1-p));
	
	int cnt = 0;
	for(int i=0;i<ans.size();i++)
		if(i==ans.size()-1 || ans[i].first ^ ans[i+1].first){
			if(ans[i].second % n != 0)
			a2.pb(ans[i]);
		}
		else 
			ans[i+1].second += ans[i].second;
	printf("%d\n",a2.size());
	for(int i=0;i<a2.size();i++)
				printf("%d%c%c",a2[i].second%n,a2[i].first?'b':'a'," \n"[i==a2.size()-1]);
}

发布了627 篇原创文章 · 获赞 91 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/103705210