class SegTree:
def __init__(self, arrVal):
self.NEUTRAL = Item(45)
self.n = len(arrVal)
self.arr = arrVal
# Empty seg
self.seg = [Item(45) for _ in range(4 * self.n)]
self.build(1, 0, self.n - 1)
def merge(self, left, right):
parent = Item(len(left.freq))
#avoids overflow
parent.invCnt = left.invCnt + right.invCnt
prev = [0] * len(left.freq)
prev[0] = right.freq[0]
for i in range(len(left.freq)):
parent.freq[i] = left.freq[i] + right.freq[i]
if i != 0:
parent.invCnt += 1 * left.freq[i] * prev[i - 1]
prev[i] = prev[i - 1] + right.freq[i]
return parent
def build(self, p, l, r):
if l == r:
self.seg[p].invCnt = 0
self.seg[p].freq[self.arr[l]] = 1
return self.seg[p]
m = (l + r) // 2
self.seg[p] = self.merge(self.build(2 * p, l, m), self.build(2 * p + 1, m + 1, r))
return self.seg[p]
def build_tree(self):
return self.build(1, 0, self.n - 1)
def set(self, i, v, p, l, r):
if i < l or i > r:
return self.seg[p]
if l == r:
self.seg[p].freq[self.arr[i]] = 0
self.seg[p].freq[v] = 1
self.arr[i] = v
return self.seg[p]
m = (l + r) // 2
self.seg[p] = self.merge(self.set(i, v, 2 * p, l, m), self.set(i, v, 2 * p + 1, m + 1, r))
return self.seg[p]
def set_value(self, i, v):
return self.set(i, v, 1, 0, self.n - 1)
def query(self, lx, rx, p, l, r):
if lx > r or l > rx:
return self.NEUTRAL
if lx <= l and r <= rx:
return self.seg[p]
m = (l + r) // 2
return self.merge(self.query(lx, rx, 2 * p, l, m), self.query(lx, rx, 2 * p + 1, m + 1, r))
def query_range(self, lx, rx):
return self.query(lx, rx, 1, 0, self.n - 1).invCnt
class Item:
def __init__(self, maxV):
self.invCnt = 0
self.freq = [0] * maxV
def main():
arr = [1, 2, 3, 6, 5, 4]
queries = [
[1, 1, 3],
[1, 2, 5],
[2, 2, 8],
[1, 1, 4]
]
st = SegTree(arr)
for query in queries:
type = query[0]
if type == 1:
l = query[1] - 1 # Making Zero based indexing
r = query[2] - 1 # Making Zero based indexing
print(st.query_range(l, r))
elif type == 2:
i = query[1] - 1 # Making Zero based indexing
v = query[2]
st.set_value(i, v)
#Driver code
if __name__ == "__main__":
main()