我的做法是,一个数要是能选,那么它对应的数一定和之前选过的数的对应的数中至少有一个相邻。
在次过程中,先分类讨论从开头开始还是结尾开始。然后开始每次枚举,按照 L,R,再就是不行的顺序讨论。
但是本蒟蒻无法证明正确性,求问大佬。
#include<cstdio>
#include<algorithm>
using namespace std;
inline int in(){
int x=0,f=1;char c;
c=getchar();
while (c<'0'||c>'9'){
if (c=='-')f=-1;
c=getchar();
}
while (c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int t,n,a[1000005],ans[500005],s[1000005],b[1000005],c[500005],pos[500005];
inline bool work(int x){
for (int i=0;i<=2*n+1;i++)s[i]=0;
if (x==0){
int l=2,r=(2*n),cnt=1;s[b[1]]=1;ans[1]=0;pos[1]=a[1];
while (cnt<n){
if (s[l]!=1&&(s[b[l]-1]+s[b[l]+1]>=1)){pos[cnt+1]=a[l];s[b[l++]]=1;ans[++cnt]=0;}
else if (s[r]!=1&&(s[b[r]-1]+s[b[r]+1]>=1)){pos[cnt+1]=a[r];s[b[r--]]=1,ans[++cnt]=1;}
else break;
}
if (cnt!=n)return 0;
else {
for (int i=1;i<=n;i++)if (ans[i]==0)printf ("L");else printf ("R");
for (int i=n;i>=1;i--){
if (pos[i]==a[l]){printf ("L");l++;}
else {printf ("R");r--;}
}
puts("");
return 1;
}
}
else {
int l=1,r=(2*n-1),cnt=1;s[b[2*n]]=1;ans[1]=1;pos[1]=a[2*n];
while (cnt<n){
if (s[l]!=1&&(s[b[l]-1]+s[b[l]+1]>=1)){pos[cnt+1]=a[l];s[b[l++]]=1;ans[++cnt]=0;}
else if (s[r]!=1&&(s[b[r]-1]+s[b[r]+1]>=1)){pos[cnt+1]=a[r];s[b[r--]]=1,ans[++cnt]=1;}
else break;
}
if (cnt!=n)return 0;
else {
for (int i=1;i<=n;i++)if (ans[i]==0)printf ("L");else printf ("R");
for (int i=n;i>=1;i--){
if (pos[i]==a[l]){printf ("L");l++;}
else {printf ("R");r--;}
}
puts("");
return 1;
}
}
}
int main(){
t=in();
while (t--){
n=in();
for (int i=1;i<=2*n;i++)c[i]=0;
for (int i=1;i<=2*n;i++){
a[i]=in();
if (c[a[i]]){
b[i]=c[a[i]];
b[c[a[i]]]=i;
}
else c[a[i]]=i;
}
if ((!work(0))&&!work(1))puts("-1");
}
return 0;
}