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;
}
posted @ 2022-07-13 10:17  gmh77  阅读(89)  评论(0编辑  收藏  举报