LGP7915题解

奇怪的乱搞做法(?

首先我们枚举序列的每一个位置,从这个位置劈开,假设这个位置是 \(i\),那么按照题意模拟,我们能够构造一个最终序列有 \(i\) 个 L 和 \(n-i\) 个 R 的符合题意的序列。

于是我们枚举所有位置,这样就有了 \(O(n^2)\) 暴力,能够在考场上拿到 65pts,性价比相当高。

然后思考正解。

我们对着样例输出可行的位置,发现这个位置的值和整个序列的第一个值一样。于是我们找到这个位置来做这个暴力,能够在洛谷数据获得 92 分的高分。

再思考一下,我们应该还要找一个位置,并且这个位置的值和整个序列的最后一个位置的值相同。

然后这题就被草过去了。。。

如果有老哥知道正确性的在麻烦评论区补充一下(

#include<algorithm>
#include<cstdio>
typedef unsigned ui;
const int M=1e6+5,mod=1e9+7;
int n,T,a[M];ui p[M],ip[M],hash[M];
ui l[M],r[M];int top,stk[M];char ans[M],s[M];bool f,vis[M];
int L,R;
inline ui Hash(const int&L,const int&R){
	return 1ull*(hash[R]-hash[L]+mod)*ip[L]%mod;
}
inline bool check(const int&L,const int&R){
	int i,h1(0),h2(0),tp;
	for(tp=0,i=L;i<=R;++i)if(!vis[i])h1=(h1+1ull*a[i]*p[++tp])%mod;
	for(tp=0,i=R;i>=L;--i)if(!vis[i])h2=(h2+1ull*a[i]*p[++tp])%mod;
	return h1==h2;
}
inline void end(){
	if(f){
		for(int i=1;i<=n;++i){
			if(s[i]<ans[i]){
				for(i=1;i<=n;++i)ans[i]=s[i];
			}
			if(s[i]>ans[i])break;
		}
	}
	else{
		f=true;for(int i=1;i<=n;++i)ans[i]=s[i];
	}
}
inline bool todo(int L1,int R1,int L2,int R2){
	if(Hash(L1,R1)==Hash(L2,R2)){
		R1-=L1-1;while(R1--)s[++L]='L';
		R2-=L2-1;while(R2--)s[R--]='R';
		return end(),true;
	}
	return false;
}
inline void make(int L1,int R1,int L2,int R2){
	int i,pL1,pR1,pL2,pR2;L=0;R=n;
	while(true){
		pL1=L1;pR1=R1;pL2=L2;pR2=R2;if(todo(L1,R1,L2,R2))return end();
		for(i=1;L1+i-1<=R1&&L1+i-1<R1-i+1;++i)if(a[L1+i-1]^a[R1-i+1])break;
		if(i^1){
			while(--i)s[++L]='L',s[R--]='L',++L1,--R1;if(todo(L1,R1,L2,R2))return end();
			if(R1+1==L1&&R2+1==L2)return end();continue;
		}
		for(i=1;L1+i-1<=R1&&L2+i-1<=R2&&L1;++i)if(a[L1+i-1]^a[L2+i-1])break;
		if(i^1){
			while(--i)s[++L]='L',s[R--]='R',++L1,++L2;if(todo(L1,R1,L2,R2))return end();
			if(R1+1==L1&&R2+1==L2)return end();continue;
		}
		for(i=1;L2+i-1<=R2&&L2+i-1<R2-i+1;++i)if(a[L2+i-1]^a[R2-i+1])break;
		if(i^1){
			while(--i)s[++L]='R',s[R--]='R',++L2,--R2;if(todo(L1,R1,L2,R2))return end();
			if(R1+1==L1&&R2+1==L2)return end();continue;
		}
		for(i=1;L1+i-1<=R1&&L2+i-1<=R2;++i)if(a[R1-i+1]^a[R2-i+1])break;
		if(i^1){
			while(--i)s[++L]='R',s[R--]='L',--R1,--R2;if(todo(L1,R1,L2,R2))return end();
			if(R1+1==L1&&R2+1==L2)return end();continue;
		}
		if(L1==pL1&&R1==pR1&&L2==pL2&&R2==pR2)return;
	}
}
signed main(){
//	freopen("palin.in","r",stdin);
//	freopen("palin.out","w",stdout);
	int i;scanf("%d",&T);p[0]=ip[0]=1;p[1]=13331;ip[1]=133822550;
	for(i=2;i<=500000;++i)p[i]=13331ull*p[i-1]%mod,ip[i]=133822550ull*ip[i-1]%mod;
	while(T--){
		scanf("%d",&n);n<<=1;f=false;
		for(i=1;i<=n;++i)scanf("%d",a+i);
		for(i=1;i<=n;++i)hash[i]=(hash[i-1]+1ull*p[i]*a[i])%mod;
		for(i=2;i<=n;++i)if(a[i]==a[1])break;
		for(int j=-1;j<=1;++j)if(i+j>=1&&i+j<=n)make(1,i+j,i+j+1,n);
		for(i=1;i<=n-1;++i)if(a[i]==a[n])break;
		for(int j=-1;j<=1;++j)if(i+j>=1&&i+j<=n)make(1,i+j,i+j+1,n);
		ans[n]='L';
		if(!f)printf("-1\n");
		else{
			for(i=1;i<=n;++i)printf("%c",ans[i]);printf("\n");
		}
	}
}
posted @ 2022-01-11 14:41  Prean  阅读(28)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};