1. 程式人生 > 其它 >CSP-S2021 迴文

CSP-S2021 迴文

【題目連結】

	https://www.luogu.com.cn/problem/P7915

【思路分析】

  首先看到的時候,我想著每次如果取了元素i,那麼如果在取到另一個之前兩者間隔的最大值能夠達到2n-cnt+1,則認為這次抽選是有效的。但是面對樣例2的時候,發現它還得有最多的約束。但這種方案最後因為擔心遇到衝突的點,而且在確定迴文串的後半部分是從左/右取的相當麻煩,故沒有寫下去。(其實在題解區有一位大神給出了證明,每次取完之後都應該存在一個排列)。
  然後看了題解恍然大悟,只要第一次抽選把棧底確定下來,之後只要滿足棧頂=棧底,即可進行取出。在程式碼實現時需要注意處理從自己一個棧裡面取的時候元素個數應該>1,而從兩個棧中取則沒有這種約束。

【程式碼】

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int T;
int n;
const int maxn = 5e5+5;
int arr[maxn<<1];
int pos[maxn][2];
int ans[maxn<<1];

void print_ans(int flag)
{
	if(flag ==0)
	{
		for(int i=1;i<=2*n;i++)
		{
			if(ans[i]==0) cout<<"L";
			else if(ans[i]==1) cout<<"R";
			else cout<<"?";
		}
	}
	else
	{
		cout<<"-1";
	}
	cout<<endl;
}

void debug_print(int lptr,int rptr)
{
	/*
	cout<<"DBG:";
	cout<<"arr["<<lptr<<"]="<<arr[lptr]<<" ";
	cout<<"arr["<<rptr<<"]="<<arr[rptr];
	cout<<endl;
	*/
}


int main()
{
	cin>>T;
	while(T--)
	{
		cin>>n;
		memset(arr,0,sizeof(arr));
		memset(pos,0,sizeof(pos));
		for(int i=1;i<=2*n;i++)
		{
			cin>>arr[i];
			if(pos[arr[i]][0]==0)
				pos[arr[i]][0]=i;
			else
				pos[arr[i]][1]=i;
			if(pos[arr[i]][0]>pos[arr[i]][1]) swap(pos[arr[i]][0],pos[arr[i]][1]);
		}
		int lst_top = 0;
		int lst_bottom = 0;
		int rst_top = 0;
		int rst_bottom = 0;
		int flag = 1;//failed
		if(flag==1)
		{
			memset(ans,-1,sizeof(ans));
			//L first
			lst_top = 2;
			lst_bottom = pos[arr[1]][1]-1;
			rst_bottom = pos[arr[1]][1]+1;
			rst_top = 2*n;
			int cnt = 1;
			ans[cnt] = 0;//left
			ans[2*n-cnt+1]=0;
			flag = 0;
			while((lst_top<=lst_bottom || rst_top>=rst_bottom) && cnt<=n)
			{
				debug_print(lst_top,lst_bottom);
				debug_print(rst_top,rst_bottom);
				if(flag==1) break;
				flag = 1;
				if(arr[lst_top]==arr[lst_bottom] && lst_top<lst_bottom)
				{
					ans[++cnt]=0;
					ans[2*n-cnt+1]=0;
					lst_top++;
					lst_bottom--;
					flag = 0;
				}
				else if(arr[lst_top]==arr[rst_bottom])
				{
					ans[++cnt]=0;
					ans[2*n-cnt+1]=1;
					lst_top++;
					rst_bottom++;
					flag = 0;
				}
				else if(arr[rst_top]==arr[lst_bottom])
				{
					ans[++cnt]=1;
					ans[2*n-cnt+1]=0;
					rst_top--;
					lst_bottom--;
					flag = 0;
				}
				else if(arr[rst_top]==arr[rst_bottom] && rst_top>rst_bottom)
				{
					ans[++cnt]=1;
					ans[2*n-cnt+1]=1;
					rst_top--;
					rst_bottom++;
					flag = 0;
				}
			}
		}
		if(flag==1)
		{
			memset(ans,-1,sizeof(ans));
			//R first
			lst_top = 1;
			lst_bottom = pos[arr[2*n]][0]-1;
			rst_bottom = pos[arr[2*n]][0]+1;
			rst_top = 2*n-1;
			int cnt = 1;
			ans[cnt] = 1;//right
			ans[2*n-cnt+1]=0;
			flag = 0;
			while((lst_top<=lst_bottom || rst_top>=rst_bottom) && cnt<=n )
			{
				debug_print(lst_top,lst_bottom);
				debug_print(rst_top,rst_bottom);
				if(flag==1) break;
				flag = 1;
				if(arr[lst_top]==arr[lst_bottom] && lst_top<lst_bottom)
				{
					ans[++cnt]=0;
					ans[2*n-cnt+1]=0;
					lst_top++;
					lst_bottom--;
					flag = 0;
				}
				else if(arr[lst_top]==arr[rst_bottom])
				{
					ans[++cnt]=0;
					ans[2*n-cnt+1]=1;
					lst_top++;
					rst_bottom++;
					flag = 0;
				}
				else if(arr[rst_top]==arr[lst_bottom])
				{
					ans[++cnt]=1;
					ans[2*n-cnt+1]=0;
					rst_top--;
					lst_bottom--;
					flag = 0;
				}
				else if(arr[rst_top]==arr[rst_bottom] && rst_top>rst_bottom)
				{
					ans[++cnt]=1;
					ans[2*n-cnt+1]=1;
					rst_top--;
					rst_bottom++;
					flag = 0;
				}
			}
		}
		print_ans(flag);
	}
	return 0;
}