Codeforces Round #551 (Div. 2) C. Serval and Parenthesis Sequence(括号匹配)(level 1)

题目链接

题意:

给你一个包含'(',')','?'的字符串。然后定义严格前缀,s[1...x] 1<=x<|s|

让你用 '(' 或 ')' 替换 '?',使得s串的严格前缀都不是正确的圆括号,但是s是正确的圆括号

圆括号的定义就是串中所有'('都能正确匹配一个')'  '()()'   '(())'

解析:

括号匹配的题目是真的做不来...想了一天...

然后想出思路,被之前写的特判卡出了,看了题目的数据才发现错了...

2

??

这个是可以的'()'

思路其实很简单,s[1]=s[2]='('

s[n-1]=s[n]=')'

然后剩下的就只需要把s[2..n-1]的串正确转换成圆括号就可以了。

做法就是先把所有‘?’换成‘(’。

然后扫一遍看多出多少个‘(’,定义x为多的‘(’个数

如果x<0||x&1都是不可能的,

然后x==0直接输出就可以了

剩下我们只需要把多出来的‘(’解决。

解决方法就是把把最靠右边的x/2个‘?’换成‘)’,即从尾扫到头,每遇到一个原来是‘?’的换成‘)’,同时x-=2

最后还需要在扫一遍检查你换的是不是正确的,如果正确的,那么输出,否则的话,就是不可能的。

因为存在这种情况

((???((())  ->  (()))((())

因为你多的可能不是由‘?’转换来的‘(’而是本身的‘(’,但是这个‘(’你是不能变的,所以只能是无解

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int N = 3e5+10;

char s[N];



char ans[N];

int main()
{
	int n;
	scanf("%d",&n);
	scanf("%s",s+1);
	int flag=0;
	int top=0;
	if(n<4||(n&1))
	{
		if(n==2)
		{
			if(strcmp(s+1,"()")==0||strcmp(s+1,"??")==0)
				printf("()\n");
			else 
				printf(":(\n");
		}
		else
		{
			printf(":(\n");
		}
		return 0;
	}
	if((s[1]=='('||s[1]=='?')&&(s[n]==')'||s[n]=='?')&&(s[2]=='('||s[2]=='?')&&(s[n-1]==')'||s[n-1]=='?'))
		flag=1;
	if(flag==0)
	{
		printf(":(\n");
		
	}
	else
	{
		int x,y;
		x=y=0;
		s[1]=ans[1]='(';
		s[2]=ans[2]='(';
		s[n]=ans[n]=')';
		s[n-1]=ans[n-1]=')';
		for(int i=2;i<=n-1;i++)
		{
			if(s[i]=='?') ans[i]='(',x++;
			else if(s[i]=='(') ans[i]='(',x++;
			else ans[i]=')',x--;
		}
		if(x>0)
		{
			for(int i=n-1;i>=2;i--)
			{
				if(x&1||x<=0) break;
				if(s[i]=='?')
				{
					x-=2;
					ans[i]=')';
				}
			}
		}
		
		if(x==0) 
		{
			int top=0;
			int flag=1;
			for(int i=2;i<=n-1;i++)
			{
				if(ans[i]=='(') top++;
				else
				{
					if(top==0)
					{
						flag=0;
						break;
					}
					top--;
				}
			}
			if(flag)
				printf("%s\n",ans+1);
			else
				printf(":(\n");
		}
		else 
			printf(":(\n");

	}


		

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值