Problem p02919 (Python) — buggy submission, verdict: Time Limit Exceeded

class Bit:
    def __init__(self, n):
        self.size = n
        self.tree = [0] * (n + 1)

    def sum(self, i):
        s = 0
        while i > 0:
            s += self.tree[i]
            i -= i & -i
        return s

    def add(self, i, x):
        while i <= self.size:
            self.tree[i] += x
            i += i & -i

    # i+1番目からR番目まで足すとt以上となるような最小のRを返す
    def bisect_plus(self, i, t):
        L = i
        R = self.size
        R_prev = R
        sum_i = self.sum(i)
        while True:
            range_sum = self.sum(R) - sum_i
            if range_sum < t:
                if R == self.size:
                    return self.size + 1
                L, R = R, R_prev
            else:
                R_prev = R
                R = (L + R + 1) // 2
                if R == R_prev:
                    return R

    # L番目からi-1番目まで足すとt以上となるような最小のRを返す
    def bisect_minus(self, i, t):
        L = 1
        R = i
        L_prev = L
        sum_i = self.sum(i - 1)
        while True:
            range_sum = sum_i - self.sum(L - 1)
            if range_sum < t:
                if L == 1:
                    return 0
                L, R = L_prev, L
            else:
                L_prev = L
                L = (L + R) // 2
                if L == L_prev:
                    return L


N = int(input())
P = list(map(int, input().split()))

place = [-1] * (N + 1)
for i in range(N):
    p = P[i]
    place[p] = i

ans = 0
big_place = Bit(N)
big_place.add(place[N] + 1, 1)
for i in range(N - 1, 0, -1):
    pos = place[i] + 1
    right = big_place.bisect_plus(pos, 1)
    right2 = big_place.bisect_plus(pos, 2)
    left = big_place.bisect_minus(pos, 1)
    left2 = big_place.bisect_minus(pos, 2)
    if left > 0:
        left_cand = left - left2
    else:
        left_cand = 0
    right_cand = right - pos
    ans += i * left_cand * right_cand

    if right < N + 1:
        right_cand = right2 - right
    else:
        right_cand = 0
    left_cand = pos - left
    ans += i * left_cand * right_cand

    big_place.add(pos, 1)

print(ans)


Error: TLE

Fixed submission:

import bisect

N = int(input())
P = list(map(int, input().split()))

place = [-1] * (N + 1)
for i in range(N):
    p = P[i]
    place[p] = i

ans = 0
big_place = [place[N]]
for i in range(N - 1, 0, -1):
    pos = bisect.bisect_left(big_place, place[i])
    if pos < len(big_place):
        right = big_place[pos]
    else:
        right = N
    if pos + 1 < len(big_place):
        right2 = big_place[pos + 1]
    else:
        right2 = N
    if pos - 1 >= 0:
        left = big_place[pos - 1]
    else:
        left = -1
    if pos - 2 >= 0:
        left2 = big_place[pos - 2]
    else:
        left2 = -1

    if left >= 0:
        left_cand = left - left2
    else:
        left_cand = 0
    right_cand = right - place[i]

    ans += i * left_cand * right_cand

    if right < N:
        right_cand = right2 - right
    else:
        right_cand = 0
    left_cand = place[i] - left
    ans += i * left_cand * right_cand

    big_place1 = big_place[:pos]
    big_place2 = big_place[pos:]
    big_place = big_place1 + [place[i]] + big_place2

print(ans)