Problem:
Score : 400 points

Problem Statement

You are given a string S of length N consisting of ( and ). Your task is to insert some number of ( and ) into S to obtain a correct bracket sequence.

Here, a correct bracket sequence is defined as follows:

() is a correct bracket sequence.

If X is a correct bracket sequence, the concatenation of (, X and ) in this order is also a correct bracket sequence.

If X and Y are correct bracket sequences, the concatenation of X and Y in this order is also a correct bracket sequence.

Every correct bracket sequence can be derived from the rules above.

Find the shortest correct bracket sequence that can be obtained. If there is more than one such sequence, find the lexicographically smallest one.

Constraints

The length of S is N.

1 ≤ N ≤ 100

S consists of ( and ).

Input

Input is given from Standard Input in the following format:

N
S

Output

Print the lexicographically smallest string among the shortest correct bracket sequences that can be obtained by inserting some number of ( and ) into S.

Sample Input 1

3
())

Sample Output 1

(())

Sample Input 2

6
)))())

Sample Output 2

(((()))())

Sample Input 3

8
))))((((

Sample Output 3

(((())))(((())))

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;




class Program 
{
    const int MOD = 1000000007;
    const int INF = 1 << 30;



    static void Main(string[] args) 
    {
        Solve();
    }



    static void Solve() 
    {
        Scaner cin = new Scaner();
        write cout = new write();
        Math2 mmath = new Math2();
        //ここから

        var o = cin.LongM;
        long N = o[0];
        var S = cin.Str;
        int left=0;
        int minleft = 0;
        for(int i = 0; i < N; ++i)
        {
            if (S[i] == '(') left++;
            else
            {
                left--;
                minleft = Math.Min(left, minleft);
            }
        }
        var x1 = new string('(', -minleft);
        var x2 = new string(')', left-minleft);
        cout.wri(x1 + S + x2);
    }


}






//b-aで降順

    //priority queue
class PriorityQueue<T> 
{
    private readonly List<T> heap;
    private readonly Comparison<T> compare;
    private int size;
    public PriorityQueue() : this(Comparer<T>.Default) {} 
    public PriorityQueue(IComparer<T> comparer) : this(16, comparer.Compare) { }
    public PriorityQueue(Comparison<T> comparison) : this(16, comparison) { }
    public PriorityQueue(int capacity, Comparison<T> comparison)
    {
        this.heap = new List<T>(capacity);
        this.compare = comparison;
    }
    public void Enqueue(T item)
    {
        this.heap.Add(item);
        var i = size++;
        while (i > 0)
        {
            var p = (i - 1) >> 1;
            if (compare(this.heap[p], item) <= 0)
                break;
            this.heap[i] = heap[p];
            i = p;
        }
        this.heap[i] = item;

    }
    public T Dequeue()
    {
        var ret = this.heap[0];
        var x = this.heap[--size];
        var i = 0;
        while ((i << 1) + 1 < size)
        {
            var a = (i << 1) + 1;
            var b = (i << 1) + 2;
            if (b < size && compare(heap[b], heap[a]) < 0) a = b;
            if (compare(heap[a], x) >= 0)
                break;
            heap[i] = heap[a];
            i = a;
        }
        heap[i] = x;
        heap.RemoveAt(size);
        return ret;
    }
    public T Peek() { return heap[0]; }
    public int Count { get { return size; } }
    public bool Any() { return size > 0; }
}


 public class Math2
{
    public long[] Fact;  //Nまでの階乗
    public long[] invFact;  //階乗の逆元

    //Nまでの階乗をセットしておく
    public void FactoricalModSet(long N,long MOD=1000000007)
    {
        Fact = new long[N + 1];
        invFact = new long[N + 1];

        Fact[0] = 1;
        for(long i = 1; i <= N; ++i)
        {
            Fact[i] = Fact[i - 1] * i%MOD;
        }
        invFact[N] = pow(Fact[N], MOD - 2);

        for (long i = N; i > 0; --i)
        {
            invFact[i - 1] = invFact[i] * i%MOD;
        }

    }

    //nCr 引数:n r (mod)
    public long nCr(long n,long r,long MOD=1000000007)
    {
        return (Fact[n] * invFact[r] % MOD * invFact[n-r]%MOD);
    }

    //階乗(O(logN)) 引数:底x n乗　(MOD)
    public long pow(long x,long n,long MOD = 1000000007)
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) != 0) res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }

    //最大公約数 引数:整数x,y
    public long GCD(long x, long y)
    {
        while (y > 0)
        {
            var r = x % y;
            x = y;
            y = r;
        }
        return x;
    }
    //最小公倍数 引数:整数x,y
    public long LCM(long x, long y)
    {
        return x * y / GCD(x, y);
    }

    //素因数分解 引数:整数N
    public Dictionary<long,int > PrimeFactorization(long N)
    {
        var ret = new Dictionary<long,int>();

        for(long i = 2; i*i <= N; ++i)
        {
            int cnt = 0;
            while (N % i == 0)
            {
                cnt++;
                N /= i;
            }
            if (cnt != 0) ret[i] = cnt;

        }
        if (N >= 2)ret[N]=1;

        return ret;

    }


}


namespace CompLib.Algorithms
{

    #region BinarySearch
    public static partial class Algorithm
    {
        static int binarySearch<T>(IList<T> a, T v, IComparer<T> cmp, bool islb)
        {
            var l = 0;
            var r = a.Count - 1;
            while (l <= r)
            {
                var m = (l + r) / 2;
                var res = cmp.Compare(a[m], v);
                if (res < 0 || (res == 0 && !islb)) l = m + 1;
                else r = m - 1;
            }
            return l;
        }

        /// <summary>
        /// 与えられた比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int LowerBound<T>(this IList<T> a, T v, Comparison<T> f) { return binarySearch(a, v, Comparer<T>.Create(f), true); }

        /// <summary>
        ///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int LowerBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, true); }

        /// <summary>
        /// 与えられた比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> 以上の要素であるような最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int UpperBound<T>(this IList<T> a, T v, Comparison<T> cmp) { return binarySearch(a, v, Comparer<T>.Create(cmp), false); }

        /// <summary>
        ///　デフォルトの比較関数に従って，<paramref name="a"/> の要素のうち，<paramref name="v"/> より真に大きい要素が現れる最小のインデックスを取得します．
        /// </summary>
        /// <typeparam name="T"><see cref="IList{T}"/> の要素の型を指定します．</typeparam>
        /// <param name="a">対象となるコレクション</param>
        /// <param name="v">対象となる要素</param>
        /// <param name="f"></param>
        /// <returns><paramref name="v"/> 以上の要素であるような最小の o-indexed でのインデックス．</returns>
        /// <remarks> <paramref name="a"/> は比較関数に対して昇順であることを仮定しています．この関数は O(log N) で実行されます．</remarks>
        public static int UpperBound<T>(this IList<T> a, T v) { return binarySearch(a, v, Comparer<T>.Default, false); }

    }
    #endregion
}







class Scaner
{
    public string Str => Console.ReadLine();

    public string[] StrM => Str.Split(' ');

    public long[] LongM => StrM.Select(long.Parse).ToArray();
    public int[] IntM => StrM.Select(int.Parse).ToArray();
    public char[] CharM => Str.ToArray();
    public long Long1 => LongM[0];
    public int Int1 => IntM[0];
    
}



class write
{
    public  void wri<T>(T x)
    {
        Console.WriteLine(x);
    }
}