1. 程式人生 > 其它 >[CSP-S 2021] 迴文 題解

[CSP-S 2021] 迴文 題解

題目大意

現有一個整數序列 \(a_1, a_2, \ldots, a_{2n}\) ,在這 \(2n\) 個數中,\(1, 2, \ldots, n\) 分別各出現恰好 \(2\) 次。現在需要建立一個長度同樣為 \(2n\) 的序列 \(b_1, b_2, \ldots, b_{2 n}\) ,初始時 \(b\) 為空序列,現在有兩種操作:

  1. 將序列 \(a\) 的開頭元素加到 \(b\) 的末尾,並從 \(a\) 中移除。
  2. 將序列 \(a\) 的末尾元素加到 \(b\) 的末尾,並從 \(a\) 中移除。

操作1用 L 表示,操作2用 R 表示,最終目的是讓 \(b\) 成為一個迴文數列 。如果可以達成目的,請輸出字典序最小的操作方案;否則,輸出 -1

分析

首先我們可以發現第1步操作只能選序列 \(a\) 最左邊或最右邊的元素,我們在此只講訴第1步選最左邊的元素的做法,而選最右邊的與此同理,不再過多贅述。
我們可以發現,如果先選 \(a_1\) ,那麼序列 \(a\) 中的有且僅有的另外一個 \(a_i=a_1\) 一定是在最後選。對於剩下的元素,進行如下兩種操作:

  • \(a_i\) 左邊的元素從左至右按從上到下的順序放進棧 \(lsta\) 中。
  • \(a_i\) 右邊的元素從右至左按從上到下的順序放進棧 \(rsta\) 中。

現在問題便轉化為了:

每次從棧 \(lsta\) 或棧 \(rsta\)的棧頂中取出一個元素放入序列 \(b\)

的末尾,最後使序列 \(b\) 成為一個迴文序列,並讓操作序列字典序最小。做法如下(此時的棧可以看作雙端佇列):

1.對於棧 \(lsta\) 的棧頂,如果棧 \(lsta\) 或棧 \(rsta\) 的棧底有與其相同的元素,則刪去這兩個元素,並記錄操作序列,跳過操作2(這是為了保證操作序列字典序最小,因為 L 字典序小於 R )。
2.對於棧 \(rsta\) 的棧頂,如果棧 \(lsta\) 或棧 \(rsta\) 的棧底有與其相同的元素,則刪去這兩個元素,並記錄操作序列。
3.如果上述操作均不能滿足,則輸出 -1 ;否則,迴圈進行上訴操作直至所有棧彈空。

舉個例子:

程式碼

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=5e5+5;
int t; 
int n;
int a[2*N],lsta[2*N],rsta[2*N];
int lbj,bj,rbj;
char ans[2*N];
int lfront,lback,rfront,rback,lans,rans;
int pd(){
	while(lans<rans){
		if(lfront>lback){
			if(rfront>=rback){
				bj=1;
				break;
			}
			if(rsta[rfront]==rsta[rback]){
				ans[lans++]='R';
				ans[rans--]='R';
				rfront++;
				rback--;
			}
			else{
				bj=1;
				break;
			}
		}
		else if(lfront==lback){
			if(rfront>rback){
				bj=1;
				break;
			}
			if(rfront==rback){
				if(lsta[lfront]==rsta[rfront]){
					ans[lans++]='L';
					ans[rans--]='R';
					lfront++;
					rfront++;
				}
				else{
					bj=1;
					break;
				}
			}
			else{
				if(lsta[lfront]==rsta[rback]){
					ans[lans++]='L';
					ans[rans--]='R';
					lfront++;
					rback--;
				}
				else if(rsta[rfront]==rsta[rback]){
					ans[lans++]='R';
					ans[rans--]='R';
					rfront++;
					rback--;
				}
				else if(lsta[lfront]==rsta[rfront]){
					ans[lans++]='R';
					ans[rans--]='L';
					lfront++;
					rfront++;
				}
				else{
					bj=1;
					break;
				}
			}
		}
		else{
			if(rfront>rback){
				if(lsta[lfront]==lsta[lback]){
					ans[lans++]='L';
					ans[rans--]='L';
					lfront++;
					lback--;
				}
				else{
					bj=1;
					break;
				}
			}
			else if(rfront==rback){
				if(lsta[lfront]==rsta[rback]){
					ans[lans++]='L';
					ans[rans--]='R';
					lfront++;
					rback--;
				}
				else if(lsta[lfront]==lsta[lback]){
					ans[lans++]='L';
					ans[rans--]='L';
					lfront++;
					lback--;
				}
				else if(lsta[lback]==rsta[rfront]){
					ans[lans++]='R';
					ans[rans--]='L';
					lback--;
					rfront++;
				}
				else{
					bj=1;
					break;
				}
			}
			else{
				if(lsta[lfront]==rsta[rback]){
					ans[lans++]='L';
					ans[rans--]='R';
					rback--;
					lfront++;
				}
				else if(lsta[lfront]==lsta[lback]){
					ans[lans++]='L';
					ans[rans--]='L';
					lback--;
					lfront++;
				}
				else if(rsta[rfront]==rsta[rback]){
					ans[lans++]='R';
					ans[rans--]='R';
					rback--;
					rfront++;
				}
				else if(rsta[rfront]==lsta[lback]){
					ans[lans++]='R';
					ans[rans--]='L';
					lback--;
					rfront++;
				}
				else{
					bj=1;
					break;
				}
			}
		}
	}
	return bj;
}
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		for(int i=1;i<=2*n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=2;i<=2*n;i++){
			if(a[i]==a[1]){
				lbj=i;
				break;
			}
		}
		ans[1]='L';
		ans[2*n]='L';
		lfront=1,lback=0,rfront=1,rback=0,lans=2,rans=2*n-1;
		for(int i=2;i<lbj;i++){
			lsta[++lback]=a[i];
		}
		for(int i=2*n;i>lbj;i--){
			rsta[++rback]=a[i];
		}
		bj=0;
		pd();
		if(bj){
			for(int i=1;i<2*n;i++){
				if(a[i]==a[2*n]){
					rbj=i;
					break;
				}
			}
			ans[1]='R';
			ans[2*n]='L';
			lfront=1,lback=0,rfront=1,rback=0,lans=2,rans=2*n-1;
			for(int i=1;i<rbj;i++){
				lsta[++lback]=a[i];
			}
			for(int i=2*n-1;i>rbj;i--){
				rsta[++rback]=a[i];
			}
			bj=0;
			pd();
			if(!bj){
				for(int i=1;i<=2*n;i++){
					printf("%c",ans[i]);
				}
				printf("\n");
			}
			else{
				printf("-1\n");
			}
		}
		else{
			for(int i=1;i<=2*n;i++){
				printf("%c",ans[i]);
			}
			printf("\n");
		}
	}
	return 0;
}