Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	var n int
	fmt.Scan(&n)

	var sc = bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	ps := make([]int, n)
	for i := range ps {
		sc.Scan()
		p, _ := strconv.Atoi(sc.Text())
		ps[i] = p
	}

	mp := make([]int, n+1)
	ans := make([]byte, 0)
	var pp, max int
	for _, p := range ps {
		mp[p] = 1
		if p < pp {
			if mp[p+1] != 1 {
				fmt.Println(":(")
				return
			}
			ans = append(ans, ')')
		} else {
			for i := max; i < p-1; i++ {
				ans = append(ans, '(')
			}
			ans = append(ans, '(')
			ans = append(ans, ')')
		}
		if p > max {
			max = p
		}
		pp = p
	}
	fmt.Println(string(ans))
}

C++: //#define NDEBUG
#include <cstddef>
#include <cstdint>
#include <vector>

using i8 = ::std::int_least8_t;
using i32 = ::std::int_least32_t;
using i64 = ::std::int_least64_t;
using u8 = ::std::uint_least8_t;
using u32 = ::std::uint_least32_t;
using u64 = ::std::uint_least64_t;
using isize = ::std::ptrdiff_t;
using usize = ::std::size_t;

template <class T = usize> class rep {
	const T f, l;

public:
	class itr {
		friend rep;
		T i;
		constexpr itr(T x) noexcept : i(x) {}

	public:
		void operator++() noexcept { ++i; }
		constexpr T operator*() const noexcept { return i; }
		constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
	};
	constexpr rep(const T first, const T last) noexcept : f(first), l(last) {}
	constexpr itr begin() const noexcept { return itr(f); }
	constexpr itr end() const noexcept { return itr(l); }
};
template <class T = usize> class revrep {
	const T f, l;

public:
	class itr {
		friend revrep;
		T i;
		constexpr itr(T x) noexcept : i(x) {}

	public:
		void operator++() noexcept { --i; }
		constexpr T operator*() const noexcept { return i; }
		constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
	};
	constexpr revrep(const T first, const T last) noexcept : f(first), l(last) {}
	constexpr itr begin() const noexcept { return itr(l - 1); }
	constexpr itr end() const noexcept { return itr(f - 1); }
};
template <class T> bool amax(T &a, const T &b) {
	return a <= b ? (a = b, 1) : 0;
}
template <class T> bool amin(T &a, const T &b) {
	return b <= a ? (a = b, 1) : 0;
}
template <class T> bool asmax(T &a, const T &b) {
	return b <= a ? 0 : (a = b, 1);
}
template <class T> bool asmin(T &a, const T &b) {
	return a <= b ? 0 : (a = b, 1);
}
template <class T> using vec_alias = ::std::vector<T>;
template <class T> auto md_vec(usize n, const T &value) {
	return ::std::vector<T>(n, value);
}
template <class... Args> auto md_vec(usize n, Args... args) {
	return ::std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
}
template <class T> const T &as_const(const T &v) noexcept { return v; }
template <class T> constexpr T difference(const T &a, const T &b) {
	return a <= b ? b - a : a - b;
}

#include <algorithm>
#include <iostream>
#include <utility>
#include<stack>
#include<string>

int main() {
	usize n;
	std::cin >> n;
	std::vector<usize> p(n), a(n);
	for (auto &e : p) {
		std::cin >> e;
		--e;
	}
	for (const auto i : rep<>(0, n)) {
		a[p[i]] = i;
	}
	std::string ans;
	std::stack<usize> st;
	st.push(n);
	usize itr = 0;
	for(const auto i : rep<>(0,n)) {
		while (itr!=n&&st.top() != i) {
			st.push(a[itr++]);
			ans.push_back('(');
		}
		if (st.top() != i) {
			std::cout << ":(" << std::endl;
			return 0;
		}
		st.pop();
		ans.push_back(')');
	}
	
	std::cout << ans << std::endl;


	return 0;
}

C++: #include <stdio.h>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <list>
#include <iterator>
#pragma warning(disable:4996)
 
typedef long long ll;
#define MIN(a, b) ((a)>(b)? (b): (a))
#define MAX(a, b) ((a)<(b)? (b): (a))
#define LINF 9223300000000000000
#define INF 2140000000
#define MOD 1000000007
using namespace std;

vector<long> ans;

bool solve( long n, const long* a, long offset )
{
    if(n<1) return true;

    long aa = a[0] - offset;
    if(aa<1 || aa>n) return false;

    ans.push_back(1);
    if (!solve( aa-1, &(a[1]), offset )) {
        return false;
    }
    ans.push_back(0);

    solve( n-aa, &(a[aa]), offset+aa );

    return true;
}

int main(int argc, char* argv[])
{
    long n;
    scanf("%ld", &n);

    vector<long> a(n);
    long i;
    for(i=0; i<n; i++) {
        long tmp;
        scanf("%ld", &tmp);
        a[tmp-1] = i+1;
    }

    if( solve( n, &(a[0]), 0 ) ) {    
        for(i=0; i<(long)ans.size(); i++) {
            if(ans[i]) printf("(");
            else       printf(")");
        }
        printf("\n");
    }
    else {
        printf(":(\n");
    }

    return 0;
}

C++: #include <iostream>
#include <bitset>
#include <fstream>
#include <string>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <deque>
#include <functional>
#include <cctype>
#include <list>
#include <limits>
//#include <boost/multiprecision/cpp_int.hpp>

const double EPS = (1e-10);


using namespace std;
using Int = long long;
//using namespace boost::multiprecision;

const Int MOD = 1000000007;

const int MAXN = 1000000;
Int fact[MAXN], inv[MAXN];

Int mod_pow(Int x, Int n) {
    Int res = 1;
    while(n > 0) {
        if(n & 1) res = (res * x) % MOD; //ビット演算(最下位ビットが1のとき)
        x = (x * x) % MOD;
        n >>= 1; //右シフト(n = n >> 1)
    }
    return res;
}

void init_fact() {
    fact[0] = 1;
    for(int i=1; i<MAXN; i++) {
        fact[i] = (fact[i-1] * i) % MOD;
    }

    inv[MAXN - 1] = mod_pow(fact[MAXN - 1], MOD-2);
    for(int i=MAXN - 2; i>=0; i--) {
        inv[i] = (inv[i+1] * (i+1)) % MOD;
    }
}

Int comb(int n, int r) {
    if(r < 0 || n < r) return 0;
    return fact[n] * inv[n-r] % MOD * inv[r] % MOD;
}

template<typename T>
T gcd(T a, T b) {
    return b != 0 ? gcd(b, a % b) : a;
}

template<typename T>
T lcm(T a, T b) {
    return a * b / gcd(a, b);
}

string s;
stack<int> st;

int main(){
    cin.tie(0);

    int n; cin >> n;
    vector<int> p(n);
    for (int i = 0; i < n; i++){
        cin >> p[i];
    }
    int ma = 0;
    for (int i = 0; i < n; i++){
        if (ma < p[i]){
            for (int j = 0; j < p[i]-ma; j++){
                s.push_back('(');
            }
            s.push_back(')');
            ma = p[i];
        }else{
            s.push_back(')');
        }
    }
    int op = 1;
    int cl = 0;
    for (int i = 0; i < s.size(); i++){
        if (s[i] == '(') st.push(op++);
        else{
            if (st.empty()){ 
                s = ":(";
                break;
            }else{
                if (p[cl] != st.top()){
                    s = ":(";
                    break;
                }else{
                    cl++;
                    st.pop();
                }
            }
        }
    }

    cout << s << endl;

    

    return 0;

}

C++: #include<iostream>
#include<stack>
using namespace std;
string s="";
int n;
int p;
main()
{
	cin>>n;
	int cnt=1;
	stack<int>S;
	for(int i=0;i<n;i++)
	{
		cin>>p;
		if(cnt<=p)
		{
			for(;cnt<=p;cnt++)
			{
				S.push(cnt);
				s+='(';
			}
		}
		if(!S.empty()&&S.top()==p)
		{
			s+=')';
			S.pop();
		}
		else
		{
			cout<<":("<<endl;
			return 0;
		}
	}
	cout<<s<<endl;
}