Parentheses

Parentheses
Input: Standard Input
Time Limit: See AtCoder
Dave loves strings consisting only of (’ and)’. Especially, he is interested in balanced strings.
Any balanced strings can be constructed using the following rules:
 A string ()” is balanced.
 Concatenation of two balanced strings are balanced.
 If T is a balanced string, concatenation of (’, T, and)’ in this order is balanced. For
example, ()()” and (()())” are balanced strings. )(” and )()(()” are not balanced
strings.
Dave has a string consisting only of (’ and)’. It satis es the followings:
 You can make it balanced by swapping adjacent characters exactly A times.
 For any non-negative integer B (B < A), you cannot make it balanced by B swaps of
adjacent characters.
 It is the shortest of all strings satisfying the above conditions.
Your task is to compute Dave’s string. If there are multiple candidates, output the minimum in
lexicographic order. As is the case with ASCII, (’ is less than)’.
Input
The input consists of a single test case, which contains an integer A(1 <= A <=  109).
Output
Output Dave’s string in one line. If there are multiple candidates, output the minimum in lexicographic order.

Sample Input 1
1

Output for the Sample Input 1
)(

There are in nitely many strings which can be balanced by only one swap. Dave’s string is the shortest of them.

Sample Input 2
4

Output for the Sample Input 2
)())((

String ))(()(” can be balanced by 4 swaps, but the output should be )())((” because it is the minimum in lexicographic order.

题意:
在一个只有‘(’,‘)’的字符串中,()是平衡的,连续的平衡字符串也是平衡的,给你一个数字a,问你怎样的字符串要通过最少a次交换相邻的字符才能变为平衡的。

分析:
这题我写时一遍直接AC了,哈哈哈。。。

这种题目一看就是要慢慢列出来然后找规律:
a=1 : )(
a=2 : )()(
a=3 : ))((
a=4 : )())((
……
a=6 : )))(((
写出了这么多后,我们会发现这样一个规律,当上一个存在()时,只要将第一个()相互交换位置就可以使最少交换次数加一。当不存在()时,就在最前面加上)(即可使最小交换次数加一。
交换第一个 ()和在前面加)(可以使其字典序最小

所以现在我们可以从一开始模拟就可以求出所以的了,但是会超时。
我们还发现不存在()的情况很特殊,))(( 的最少交换次数为(2 * 3) / 2 ,)))(((的最少交换次数为(3 * 4) / 2…… 所以t个)和t个(构成的字符串最小的交换次数为(t*(t+1))/2

最后我们先求出t*(t+1)<=2*a 的最大的t,然后在进行处理就可以了。

AC代码:

#include <iostream>
using namespace std;
int main()
{
	int a ;
	while(cin >> a)
	{
		int t = 1 ;
		while(t * (t + 1) <= 2 * a) t ++ ;
		t -- ;
		if(t * (t + 1) == 2 * a) 
		 {
		 	t *= 2 ;
		 	for(int i = 1;i <= t / 2 ;i ++)
		 	 printf(")") ;
		 	for(int i = 1 ;i <= t / 2;i ++)
		 	 printf("(") ;
		 	puts("") ;
		 }
		 else 
		 {
		 	
		 	int i = 1 ;
		 	int c = a - t * (t + 1) / 2 ;
		 	for( ;i <= c ;i ++)
		 	 printf(")") ;
		 	printf("(") ;
		 	i ++ ;
		 	for( ;i <= t + 2 ;i ++)
		 	 printf(")") ;
		 	for( int i = 1 ;i <= t ;i ++)
		 	 printf("(") ;
		 	puts("") ;
		 }
	}
	return 0 ;
}
每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
原文地址:https://www.cnblogs.com/spnooyseed/p/12870916.html