过了,但是求问做法正确性
查看原帖
过了,但是求问做法正确性
761649
ryf_loser楼主2025/8/30 22:00

我的做法是,一个数要是能选,那么它对应的数一定和之前选过的数的对应的数中至少有一个相邻。

在次过程中,先分类讨论从开头开始还是结尾开始。然后开始每次枚举,按照 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;
}

2025/8/30 22:00
加载中...