Problem p02919 (python)

Fixed submission:
# 区間ではなく各要素を独立に考える典型のやつ

# ある値について条件を満たすようにしたいとき
# その値より大きいものだけ探せば良い
# 具体的には自分より大きい値を1つだけ含むような区間が条件を満たす

# 愚直にやると各値について, その左右を近い方から順に見ていかなければならず間に合わない
# 自分より大きい値だけ知りたいので, 要素の大きい順に見ていくことで計算量が減る

# 普通にやったのが下のコードでAC+TLE(恐らく合ってる)

def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    import math
    #from math import gcd

    #inf = 10**17
    #mod = 10**9 + 7

    n = int(input())
    p = list(map(int, input().split()))

    # 1-indexed
    # f[i]:要素iのインデックス
    f = [0]*(n+1)
    for i in range(n):
        f[p[i]] = i+1

    # 各要素よりも大きい値のインデックスを参照するための配列
    l = [0] + [i for i in range(n+1)]
    r = [i + 1 for i in range(n+1)] + [n+1]

    res = 0

    for i in range(1,n+1):
        # x:要素iのインデックス
        x = f[i]
        
        # iは1から見ていくので, 選んだ時点でiより大きい数のインデックスが分かる
        l1,r1 = l[x],r[x]
        l2,r2 = l[l1],r[r1]

        res += ((l1-l2)*(r1-x) + (x-l1)*(r2-r1))*i

        # 要素iのインデックスをこれ以降参照することはないので消す
        l[r1],r[l1] = l1,r1

    print(res)

if __name__ == '__main__':
    main()

Buggy submission (verdict: Runtime Error):
def main():
    import sys
    input = sys.stdin.readline
    sys.setrecursionlimit(10**7)
    from collections import Counter, deque
    from itertools import combinations, permutations, accumulate, groupby, product
    from bisect import bisect_left,bisect_right
    from heapq import heapify, heappop, heappush
    import math
    #from math import gcd

    #inf = 10**17
    #mod = 10**9 + 7

    class minseg():
        
        def __init__(self, arr):
            self.n = len(arr)
            self.ide_ele = arr[0]
            self.num =2**((self.n-1).bit_length())
            self.seg=[self.ide_ele]*2*self.num
            for i in range(self.n):
                self.seg[i+self.num-1]=arr[i]
            for i in range(self.num-2,-1,-1) :
                self.seg[i]=self.segfunc(self.seg[2*i+1],self.seg[2*i+2]) 

        def segfunc(self, x, y):
            return min(x, y)

            
        def update(self, k, x):
            k += self.num-1
            self.seg[k] = x
            while k:
                k = (k-1)//2
                self.seg[k] = self.segfunc(self.seg[k*2+1],self.seg[k*2+2])
            
        def query(self, p, q):
            if q<=p:
                return self.ide_ele
            p += self.num-1
            q += self.num-2
            res=self.ide_ele
            while q-p>1:
                if p&1 == 0:
                    res = self.segfunc(res,self.seg[p])
                if q&1 == 1:
                    res = self.segfunc(res,self.seg[q])
                    q -= 1
                p = p//2
                q = (q-1)//2
            if p == q:
                res = self.segfunc(res,self.seg[p])
            else:
                res = self.segfunc(self.segfunc(res,self.seg[p]),self.seg[q])
            return res

    class maxseg():
        
        def __init__(self, arr):
            self.n = len(arr)
            self.ide_ele = arr[0]
            self.num =2**((self.n-1).bit_length())
            self.seg=[self.ide_ele]*2*self.num
            for i in range(self.n):
                self.seg[i+self.num-1]=arr[i]
            for i in range(self.num-2,-1,-1) :
                self.seg[i]=self.segfunc(self.seg[2*i+1],self.seg[2*i+2]) 

        def segfunc(self, x, y):
            return max(x, y)

            
        def update(self, k, x):
            k += self.num-1
            self.seg[k] = x
            while k:
                k = (k-1)//2
                self.seg[k] = self.segfunc(self.seg[k*2+1],self.seg[k*2+2])
            
        def query(self, p, q):
            if q<=p:
                return self.ide_ele
            p += self.num-1
            q += self.num-2
            res=self.ide_ele
            while q-p>1:
                if p&1 == 0:
                    res = self.segfunc(res,self.seg[p])
                if q&1 == 1:
                    res = self.segfunc(res,self.seg[q])
                    q -= 1
                p = p//2
                q = (q-1)//2
            if p == q:
                res = self.segfunc(res,self.seg[p])
            else:
                res = self.segfunc(self.segfunc(res,self.seg[p]),self.seg[q])
            return res

    n = int(input())
    a = list(map(int, input().split()))

    ind = {}
    for i in range(n):
        ind[a[i]] = i
    smax = maxseg([0]*n)
    smin = minseg([n+1]*n)

    res = 0
    for i in range(n):
        # 配列の1-indexed
        pos = ind[n-i] + 1

        l1 = smax.query(0, pos)
        l2 = smax.query(0, l1)
        r1 = smin.query(pos, n+2)
        r2 = smin.query(r1+1, n+2)
        res += ((l1-l2)*(r1-pos) + (r2-r1)*(pos-l1)) * (n-i)

        smin.update(pos, pos)
        smax.update(pos, pos)

    print(res)

if __name__ == '__main__':
    main()