[CSP-S 2021] 迴文 題解
阿新 • • 發佈:2022-05-05
題目大意
現有一個整數序列 \(a_1, a_2, \ldots, a_{2n}\) ,在這 \(2n\) 個數中,\(1, 2, \ldots, n\) 分別各出現恰好 \(2\) 次。現在需要建立一個長度同樣為 \(2n\) 的序列 \(b_1, b_2, \ldots, b_{2 n}\) ,初始時 \(b\) 為空序列,現在有兩種操作:
- 將序列 \(a\) 的開頭元素加到 \(b\) 的末尾,並從 \(a\) 中移除。
- 將序列 \(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\)
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; }