arc141C - Bracket and Permutation

半年沒寫題解了,寫一篇來冒個泡

題目大意

給出長2n的排列p和q,求長2n的括號序列S(左右括號分別n個,不要求合法),使得在所有將S帶編號重排得到合法括號序的編號排列中,p是字典序最小的排列,q是字典序最大的排列

題解

很神仙的題,完全沒有思路,題解也沒說人話

把S寫成折線,一部分在y=0上,一部分在y=0下

觀察可得,在求字典序最小的p時,在y=0上的對應一段連續編號,在y=0下的對應 最近的左括號,最近的右括號,次近的左括號,次近的右括號…… 這樣的序列

(原理可以模擬,把左右括號分別排序,若sum>0則取兩者位置最前的,否則取左括號,因爲sum一直>=0所以每次都會取最小的,即按順序取)

這樣可以按左右左右的順序得到在y=0下的所有括號(在y=0上的求不出來)

同理,用q可以求出在y=0上的所有括號,二者拼起來就是答案

具體實現,就是找p[i]>p[i+1]和q[i]<q[i+1]的,分別設爲左右括號,沒填完就-1,最後check一下

(因爲對於p來說,在y=0下的一定是先取後面的左括號,再取前面的右括號,故p[i]>p[i+1],q同理)

code

#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
//#define file
using namespace std;

int n,i,j,k,l,sum;
int p[400001],q[400001];
int P[400001],Q[400001];
int a[400001],A[200001],B[200001];

void Exit()
{
	printf("-1\n");
	exit(0);
}

void check1()
{
	i=j=1,l=0;sum=0;
	while (i<=n || j<=n)
	{
		if (!sum)
		{
			if (i<=n)
			P[++l]=A[i++],++sum;
			else
			Exit();
		}
		else
		{
			if (i<=n)
			{
				if (j<=n)
				{
					if (A[i]<B[j])
					P[++l]=A[i++],++sum;
					else
					P[++l]=B[j++],--sum;
				}
				else
				P[++l]=A[i++],++sum;
			}
			else
			P[++l]=B[j++],--sum;
		}
	}
	fo(i,1,n*2) if (p[i]!=P[i]) Exit();
}

void check2()
{
	i=j=n,l=0;sum=0;
	while (i || j)
	{
		if (!sum)
		{
			if (i)
			Q[++l]=A[i--],++sum;
			else
			Exit();
		}
		else
		{
			if (i)
			{
				if (j)
				{
					if (A[i]>B[j])
					Q[++l]=A[i--],++sum;
					else
					Q[++l]=B[j--],--sum;
				}
				else
				Q[++l]=A[i--],++sum;
			}
			else
			Q[++l]=B[j--],--sum;
		}
	}
	fo(i,1,n*2) if (q[i]!=Q[i]) Exit();
}

int main()
{
	#ifdef file
	freopen("arc141C.in","r",stdin);
	#endif
	
	scanf("%d",&n);
	fo(i,1,n*2) scanf("%d",&p[i]);
	fo(i,1,n*2) scanf("%d",&q[i]);
	
	for (i=1; i<=n*2; i+=2) if (p[i]>p[i+1]) a[p[i]]=1,a[p[i+1]]=-1;
	for (i=1; i<=n*2; i+=2) if (q[i]<q[i+1]) a[q[i]]=1,a[q[i+1]]=-1;
	
	fo(i,1,n*2) if (!a[i]) Exit();
	
	k=l=0;
	fo(i,1,n*2) if (a[i]==1) A[++k]=i; else B[++l]=i;
	
	check1();
	check2();
	
	fo(i,1,n*2)
	printf((a[i]==1)?"(":")");
	printf("\n");
	
	fclose(stdin);
	fclose(stdout);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章