Buggy python submission (verdict: Time Limit Exceeded):
# http://tsutaj.hatenablog.com/entry/2017/03/29/204841
class SegmentTree:
    def __init__(self, v, func, init_val):
        self.func = func
        self.init_val = init_val

        sz = len(v)

        self.n = 1
        while self.n < sz:
            self.n *= 2

        self.node = [self.init_val for _ in range(2 * self.n - 1)]
        # 元配列 v をセグメント木で表現する
        # 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
        # セグメント木全体で必要なノード数は 2n - 1 個である

        for i in range(sz):
            self.node[i + self.n - 1] = v[i]
        # 最下段に値を入れたあとに、下の段から順番に値を入れる

        for i in range(self.n - 2, -1, -1):
            self.node[i] = self.func(self.node[2 * i + 1], self.node[2 * i + 2])
        # 値を入れるには、自分の子の 2 値を参照すれば良い

    def update(self, x, val):
        x += self.n - 1
        # 最下段のノードにアクセスする

        self.node[x] = val
        while x > 0:
            x = (x - 1) // 2
            self.node[x] = self.func(self.node[2 * x + 1], self.node[2 * x + 2])
        # 最下段のノードを更新したら、あとは親に上って更新していく

    # 要求区間 [a, b) 中の要素の最小値を答える
    # k := 自分がいるノードのインデックス
    # 対象区間は [l, r) にあたる

    def get_val(self, a, b, k=0, l=0, r=-1):
        if r < 0: r = self.n
        # 最初に呼び出されたときの対象区間は [0, self.n)

        if r <= a or b <= l: return self.init_val
        # 要求区間と対象区間が交わらない -> 適当に返す

        if a <= l and r <= b: return self.node[k]
        # 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う

        vl = self.get_val(a, b, 2 * k + 1, l, (l + r) // 2)
        vr = self.get_val(a, b, 2 * k + 2, (l + r) // 2, r)
        return self.func(vl, vr)
        # 要求区間が対象区間の一部を被覆 -> 子について探索を行う
        # 左側の子を vl ・ 右側の子を vr としている
        # 新しい対象区間は、現在の対象区間を半分に割ったもの


def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)


N = int(input())
a = tuple(map(int, input().split()))

st = SegmentTree(v=a, func=gcd, init_val=0)

g = max(gcd(st.get_val(0, drop_idx), st.get_val(drop_idx + 1, N)) for drop_idx in range(N))
print(g)


Fixed submission:
def gcd(a, b):
    if b == 0: return a
    return gcd(b, a % b)


N = int(input())
a = list(map(int, input().split()))
a.sort()

g_left = []
g_right = []

t = a[0]
for i in range(N):
    t = gcd(t, a[i])
    g_left.append(t)

t = a[-1]
for i in range(N - 1, -1, -1):
    t = gcd(t, a[i])
    g_right.append(t)

g_right.reverse()

g = 1
for i in range(1, N - 1):
    g = max(g, gcd(g_left[i - 1], g_right[i + 1]))
g = max(g, g_left[N - 2])
g = max(g, g_right[1])

print(g)

Buggy python submission (verdict: Time Limit Exceeded):
# http://tsutaj.hatenablog.com/entry/2017/03/29/204841
class SegmentTree:
    def __init__(self, v, func, init_val):
        self.func = func
        self.init_val = init_val

        sz = len(v)

        self.n = 1
        while self.n < sz:
            self.n *= 2

        self.node = [self.init_val for _ in range(2 * self.n - 1)]
        # 元配列 v をセグメント木で表現する
        # 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
        # セグメント木全体で必要なノード数は 2n - 1 個である

        for i in range(sz):
            self.node[i + self.n - 1] = v[i]
        # 最下段に値を入れたあとに、下の段から順番に値を入れる

        for i in range(self.n - 2, -1, -1):
            self.node[i] = self.func(self.node[2 * i + 1], self.node[2 * i + 2])
        # 値を入れるには、自分の子の 2 値を参照すれば良い

    def update(self, x, val):
        x += self.n - 1
        # 最下段のノードにアクセスする

        self.node[x] = val
        while x > 0:
            x = (x - 1) // 2
            self.node[x] = min(self.node[2 * x + 1], self.node[2 * x + 2])
        # 最下段のノードを更新したら、あとは親に上って更新していく

    # 要求区間 [a, b) 中の要素の最小値を答える
    # k := 自分がいるノードのインデックス
    # 対象区間は [l, r) にあたる

    def get_val(self, a, b, k=0, l=0, r=-1):
        if r < 0: r = self.n
        # 最初に呼び出されたときの対象区間は [0, self.n)

        if r <= a or b <= l: return self.init_val
        # 要求区間と対象区間が交わらない -> 適当に返す

        if a <= l and r <= b: return self.node[k]
        # 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う

        vl = self.get_val(a, b, 2 * k + 1, l, (l + r) // 2)
        vr = self.get_val(a, b, 2 * k + 2, (l + r) // 2, r)
        return self.func(vl, vr)
        # 要求区間が対象区間の一部を被覆 -> 子について探索を行う
        # 左側の子を vl ・ 右側の子を vr としている
        # 新しい対象区間は、現在の対象区間を半分に割ったもの


def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)


N = int(input())
a = tuple(map(int, input().split()))

st = SegmentTree(v=a, func=gcd, init_val=0)

g = max(gcd(st.get_val(0, drop_idx), st.get_val(drop_idx + 1, N)) for drop_idx in range(N))
print(g)


Fixed submission:
def gcd(a, b):
    if b == 0: return a
    return gcd(b, a % b)


N = int(input())
a = list(map(int, input().split()))
a.sort()

g_left = []
g_right = []

t = a[0]
for i in range(N):
    t = gcd(t, a[i])
    g_left.append(t)

t = a[-1]
for i in range(N - 1, -1, -1):
    t = gcd(t, a[i])
    g_right.append(t)

g_right.reverse()

g = 1
for i in range(1, N - 1):
    g = max(g, gcd(g_left[i - 1], g_right[i + 1]))
g = max(g, g_left[N - 2])
g = max(g, g_right[1])

print(g)

Buggy python submission (verdict: Time Limit Exceeded):
# http://tsutaj.hatenablog.com/entry/2017/03/29/204841
class SegmentTree:
    def __init__(self, v, func, init_val):
        self.func = func
        self.init_val = init_val

        sz = len(v)

        self.n = 1
        while self.n < sz:
            self.n *= 2

        self.node = [self.init_val for _ in range(2 * self.n - 1)]
        # 元配列 v をセグメント木で表現する
        # 最下段のノード数は元配列のサイズ以上になる最小の 2 冪 -> これを n とおく
        # セグメント木全体で必要なノード数は 2n - 1 個である

        for i in range(sz):
            self.node[i + self.n - 1] = v[i]
        # 最下段に値を入れたあとに、下の段から順番に値を入れる

        for i in range(self.n - 2, -1, -1):
            self.node[i] = self.func(self.node[2 * i + 1], self.node[2 * i + 2])
        # 値を入れるには、自分の子の 2 値を参照すれば良い

    def update(self, x, val):
        x += self.n - 1
        # 最下段のノードにアクセスする

        self.node[x] = val
        while x > 0:
            x = (x - 1) // 2
            self.node[x] = min(self.node[2 * x + 1], self.node[2 * x + 2])
        # 最下段のノードを更新したら、あとは親に上って更新していく

    # 要求区間 [a, b) 中の要素の最小値を答える
    # k := 自分がいるノードのインデックス
    # 対象区間は [l, r) にあたる

    def get_val(self, a, b, k=0, l=0, r=-1):
        if r < 0: r = self.n
        # 最初に呼び出されたときの対象区間は [0, self.n)

        if r <= a or b <= l: return self.init_val
        # 要求区間と対象区間が交わらない -> 適当に返す

        if a <= l and r <= b: return self.node[k]
        # 要求区間が対象区間を完全に被覆 -> 対象区間を答えの計算に使う

        vl = self.get_val(a, b, 2 * k + 1, l, (l + r) // 2)
        vr = self.get_val(a, b, 2 * k + 2, (l + r) // 2, r)
        return self.func(vl, vr)
        # 要求区間が対象区間の一部を被覆 -> 子について探索を行う
        # 左側の子を vl ・ 右側の子を vr としている
        # 新しい対象区間は、現在の対象区間を半分に割ったもの


def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)


N = int(input())
a = tuple(map(int, input().split()))

st = SegmentTree(v=a, func=gcd, init_val=0)

g = max(gcd(st.get_val(0, drop_idx), st.get_val(drop_idx + 1, N)) for drop_idx in range(N))
print(g)


Fixed submission:
def gcd(a, b):
    if b == 0: return a
    return gcd(b, a % b)


N = int(input())
a = list(map(int, input().split()))
a.sort()

g_left = []
g_right = []

t = a[0]
for i in range(N):
    t = gcd(t, a[i])
    g_left.append(t)

t = a[-1]
for i in range(N - 1, -1, -1):
    t = gcd(t, a[i])
    g_right.append(t)

g_right.reverse()

g = 1
for i in range(1, N - 1):
    g = max(g, gcd(g_left[i - 1], g_right[i + 1]))
g = max(g, g_left[N - 2])
g = max(g, g_right[1])

print(g)

Buggy python submission (verdict: Time Limit Exceeded):
def gcd(a, b):
    return a if b == 0 else gcd(b, a % b)


N = int(input())
a = map(int, input().split())

N_MAX = 1 << N.bit_length()

v = [0 for _ in range(2 * N_MAX - 1)]
# Segment Tree

for idx, aa in enumerate(a):
    idx += N_MAX - 1  # Segment Treeの葉ノードのIndexに変換
    v[idx] = aa
    while idx > 0:
        idx = (idx - 1) // 2  # 親ノードのIndexに変換
        v[idx] = gcd(v[idx * 2 + 1], v[idx * 2 + 2])  # ノードの値は、2つの子ノードの値の最大公約数

# print(v)

def query(a, b, k=0, l=0, r=N_MAX):
    # [a,b)の最大公約数
    # print(a, b, k, l, r)
    if r <= a or b <= l: return 0  # 交差しない
    if a <= l and r <= b: return v[k]  # 含まれる
    gcd_l = query(a, b, 2 * k + 1, l, (l + r) // 2)
    gcd_r = query(a, b, 2 * k + 2, (l + r) // 2, r)
    return gcd(gcd_l, gcd_r)


g = 0
for i in range(N):
    g = max(g, gcd(query(0, i), query(i + 1, N)))
print(g)


Fixed submission:
def gcd(a, b):
    if b == 0: return a
    return gcd(b, a % b)


N = int(input())
a = list(map(int, input().split()))
a.sort()

g_left = []
g_right = []

t = a[0]
for i in range(N):
    t = gcd(t, a[i])
    g_left.append(t)

t = a[-1]
for i in range(N - 1, -1, -1):
    t = gcd(t, a[i])
    g_right.append(t)

g_right.reverse()

g = 1
for i in range(1, N - 1):
    g = max(g, gcd(g_left[i - 1], g_right[i + 1]))
g = max(g, g_left[N - 2])
g = max(g, g_right[1])

print(g)