Problem:


Score : 600 points

Problem Statement

We have N colored balls arranged in a row from left to right; the color of the i-th ball from the left is c_i.

You are given Q queries. The i-th query is as follows: how many different colors do the l_i-th through r_i-th balls from the left have?

Constraints

1\leq N,Q \leq 5 \times 10^5

1\leq c_i \leq N

1\leq l_i \leq r_i \leq N

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N Q
c_1 c_2 \cdots c_N
l_1 r_1
l_2 r_2
:
l_Q r_Q

Output

Print Q lines. The i-th line should contain the response to the i-th query.

Sample Input 1

4 3
1 2 1 3
1 3
2 4
3 3

Sample Output 1

2
3
1

The 1-st, 2-nd, and 3-rd balls from the left have the colors 1, 2, and 1 - two different colors.

The 2-st, 3-rd, and 4-th balls from the left have the colors 2, 1, and 3 - three different colors.

The 3-rd ball from the left has the color 1 - just one color.

Sample Input 2

10 10
2 5 6 5 2 1 7 9 7 2
5 5
2 4
6 7
2 2
7 8
7 9
1 8
6 9
8 10
6 8

Sample Output 2

1
2
2
1
2
2
6
3
3
3



Sample input:
4 3
1 2 1 3
1 3
2 4
3 3


Sample output:
2
3
1

Submission status: Accepted

Solution code:
class BinaryIndexedTree:
    def __init__(self, size=10**7):
        self.size = size
        self.data = [0]*(size+1)

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

    def prefix_sum(self, index):
        res = 0
        while index >= 1:
            res += self.data[index]
            index -= index & -index
        return res
    
    def interval_sum(self, left, right):
        return self.prefix_sum(right) - self.prefix_sum(left-1)

    def __getitem__(self, index):
        return self.sum(index) - self.sum(index-1)

    # def __setitem__(self, index, x):
    #     before = self.__getitem__(index)
    #     self.add(index, -before)
    #     self.add(index, x)

def main():
    from sys import stdin
    input = lambda: stdin.readline()
    LMIIS = lambda: list(map(int,input().split()))


    N,Q = LMIIS()
    # 1-indexedにするためリストの先頭に0を追加
    C = [0] + LMIIS()

    # クエリを保存するリストのリスト, r -> (l,クエリの順番)のリスト
    queries = []
    for i in range(N+1):
        queries.append([])

    # クエリを保存
    for i in range(Q):
        l,r = map(int,input().split())
        queries[r].append((l,i))

    # 玉の種類 -> 良い玉の場所
    good_ball_places = [0] * (N+1)

    # 場所 -> 良い玉が存在するなら1,しないなら0
    good_ball_exists = BinaryIndexedTree(N)

    #　玉の更新済み範囲
    k = 0
    # クエリの回答
    out = [0] * Q
    for r,query in enumerate(queries):
        for l,order in query:
            for i in range(k+1,r+1):
                # 位置iの玉の色
                color = C[i]
                # 色colorの良い玉の前の位置
                before = good_ball_places[color]
                # 色colorが既出なら、前の位置での存在を消去
                if 0 < before:
                    good_ball_exists.add(before,-1)
                # 色colorの良い玉の位置はi
                good_ball_places[color] = i
                # 位置iに良い玉が存在
                good_ball_exists.add(i,1)
            # 良い玉を更新した範囲
            k = r
            # [l,r]に存在する良い玉の数の合計
            out[order] = good_ball_exists.interval_sum(l,r)
    print('\n'.join(map(str,out)))


        








    
main()

Submission status: Accepted

Solution code:
class BinaryIndexedTree:
    def __init__(self, size=10**7):
        self.size = size
        self.data = [0]*(size+1)

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

    def prefix_sum(self, index):
        res = 0
        while index >= 1:
            res += self.data[index]
            index -= index & -index
        return res
    
    def interval_sum(self, left, right):
        return self.prefix_sum(right) - self.prefix_sum(left-1)

    def __getitem__(self, index):
        return self.sum(index) - self.sum(index-1)

    # def __setitem__(self, index, x):
    #     before = self.__getitem__(index)
    #     self.add(index, -before)
    #     self.add(index, x)

def main():
    from sys import stdin
    input = lambda: stdin.readline()
    LMIIS = lambda: list(map(int,input().split()))


    N,Q = LMIIS()
    # 1-indexedにするためリストの先頭に0を追加
    C = [0] + LMIIS()
    queries = []

    # 順番と一緒にクエリを保存
    for i in range(Q):
        l,r = map(int,input().split())
        queries.append((i,l,r))
    
    # rについてクエリをソート
    queries.sort(key=lambda x: x[2])

    # 玉の種類 -> 良い玉の場所
    good_ball_places = [0] * (N+1)

    # 場所 -> 良い玉が存在するなら1,しないなら0
    good_ball_exists = BinaryIndexedTree(N)

    #　玉の更新済み範囲
    k = 0
    # クエリの回答
    out = [0] * Q
    for order,l,r in queries:
        for i in range(k+1,r+1):
            # 位置iの玉の色
            color = C[i]
            # 色colorの良い玉の前の位置
            before = good_ball_places[color]
            # 色colorが既出なら、前の位置での存在を消去
            if 0 < before:
                good_ball_exists.add(before,-1)
            # 色colorの良い玉の位置はi
            good_ball_places[color] = i
            # 位置iに良い玉が存在
            good_ball_exists.add(i,1)
        # 良い玉を更新した範囲
        k = r
        # [l,r]に存在する良い玉の数の合計
        out[order] = good_ball_exists.interval_sum(l,r)
    print('\n'.join(map(str,out)))


        








    
main()

Submission status: Accepted

Solution code:
class BinaryIndexedTree:
    def __init__(self, size=10**7):
        self.size = size
        self.data = [0]*(size+1)

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

    def prefix_sum(self, index):
        res = 0
        while index >= 1:
            res += self.data[index]
            index -= index & -index
        return res
    
    def interval_sum(self, left, right):
        return self.prefix_sum(right) - self.prefix_sum(left-1)

    def __getitem__(self, index):
        return self.sum(index) - self.sum(index-1)

    # def __setitem__(self, index, x):
    #     before = self.__getitem__(index)
    #     self.add(index, -before)
    #     self.add(index, x)

def main():
    from sys import stdin
    input = lambda: stdin.readline()
    LMIIS = lambda: list(map(int,input().split()))


    N,Q = LMIIS()
    # 1-indexedにするためリストの先頭に0を追加
    C = [0] + LMIIS()
    queries = []

    # 順番と一緒にクエリを保存
    for i in range(Q):
        l,r = map(int,input().split())
        queries.append((i,l,r))
    
    # rについてクエリをソート
    queries.sort(key=lambda x: x[2])

    # 玉の種類 -> 良い玉の場所
    good_ball_places = [0] * (N+1)

    # 場所 -> 良い玉が存在するなら1,しないなら0
    good_ball_exists = BinaryIndexedTree()

    #　玉の更新済み範囲
    k = 0
    # クエリの回答
    out = [0] * Q
    for order,l,r in queries:
        for i in range(k+1,r+1):
            # 位置iの玉の色
            color = C[i]
            # 色colorの良い玉の前の位置
            before = good_ball_places[color]
            # 色colorが既出なら、前の位置での存在を消去
            if 0 < before:
                good_ball_exists.add(before,-1)
            # 色colorの良い玉の位置はi
            good_ball_places[color] = i
            # 位置iに良い玉が存在
            good_ball_exists.add(i,1)
        # 良い玉を更新した範囲
        k = r
        # [l,r]に存在する良い玉の数の合計
        out[order] = good_ball_exists.interval_sum(l,r)
    print('\n'.join(map(str,out)))


        








    
main()

Submission status: Accepted

Solution code:
import os
import sys
import numpy as np

def proc(C, L, R, Order, N, Q):
    pl = pr = 0
    ans = 0
    A = np.zeros(N+1, dtype=np.int32)
    Ans = np.zeros(Q, dtype=np.int32)
    for idx_LR in Order:
        l = L[idx_LR]
        r = R[idx_LR]
        while pr < r:
            pr += 1
            c = C[pr]
            if A[c] == 0:
                ans += 1
            A[c] += 1
        while pl > l:
            pl -= 1
            c = C[pl]
            if A[c] == 0:
                ans += 1
            A[c] += 1
        while pr > r:
            c = C[pr]
            A[c] -= 1
            if A[c] == 0:
                ans -= 1
            pr -= 1
        while pl < l:
            c = C[pl]
            A[c] -= 1
            if A[c] == 0:
                ans -= 1
            pl += 1
        Ans[idx_LR] = ans
    return Ans


# >>> numba compile >>>
numba_config = [
    [proc, "i4[:](i4[:],u4[:],u4[:],i8[:],i4,i4)"],
]
if sys.argv[-1] == "ONLINE_JUDGE":
    from numba import njit
    from numba.pycc import CC
    cc = CC("my_module")
    for func, signature in numba_config:
        vars()[func.__name__] = njit(signature)(func)
        cc.export(func.__name__, signature)(func)
    cc.compile()
    exit()
elif os.name == "posix":
    exec(f"from my_module import {','.join(func.__name__ for func, _ in numba_config)}")
else:
    from numba import njit
    for func, signature in numba_config:
        vars()[func.__name__] = njit(signature, cache=True)(func)
    print("compiled!", file=sys.stderr)
# <<< numba compile <<<


def main():
    input = sys.stdin.buffer.readline
    N, Q = map(int, input().split())
    C = np.empty(N+1, dtype=np.int32)
    C[0] = 0
    C[1:] = np.array(input().split(), dtype=np.int32)
    LR = np.array(sys.stdin.buffer.read().split(), dtype=np.uint32)
    L = LR[::2]
    R = LR[1::2]
    B = L>>9<<20|R
    Idx = (L>>9&1).astype(np.bool)
    B[Idx] = L[Idx]>>9<<20|(1<<20)-R[Idx]
    Order = np.argsort(B)
    Ans = proc(C, L, R, Order, N, Q)
    print("\n".join(map(str, Ans.tolist())))

main()

Submission status: Accepted

Solution code:
from sys import stdin
input = stdin.readline
n, q = map(int ,input().split())
c = list(map(int, input().split()))
data = []
for i in range(q):
    data.append([i] + list(map(int, input().split())))
data.sort(key=lambda x : x[2])
ans = [0 for i in range(q)]
#####segfunc######
def segfunc(x,y):
    return x + y

def init(init_val):
    #set_val
    for i in range(len(init_val)):
        seg[i+num-1]=init_val[i]   
    #built
    for i in range(num-2,-1,-1) :
        seg[i]=segfunc(seg[2*i+1],seg[2*i+2]) 
    
def update(k,x):
    k += num-1
    seg[k] = x
    while k:
        k = (k-1)//2
        seg[k] = segfunc(seg[k*2+1],seg[k*2+2])
    
def query(p,q):
    if q<=p:
        return ide_ele
    p += num-1
    q += num-2
    res=ide_ele
    while q-p>1:
        if p&1 == 0:
            res = segfunc(res,seg[p])
        if q&1 == 1:
            res = segfunc(res,seg[q])
            q -= 1
        p = p//2
        q = (q-1)//2
    if p == q:
        res = segfunc(res,seg[p])
    else:
        res = segfunc(segfunc(res,seg[p]),seg[q])
    return res

#####単位元######
ide_ele = 0 
num = 2**(n-1).bit_length()
seg=[ide_ele]*(2*num - 1)
good_ball = dict()
pre_r = 0
count = 0
for i in range(q):
    index, l, r = data[i]
    l, r = l-1, r-1
    for j in range(pre_r, r+1):
        if c[j] in good_ball: 
            update(good_ball[c[j]], 0)           
        update(j, 1)
        good_ball[c[j]] = j
    pre_r = r + 1
    ans[index] = query(l, r+1)
for i in range(q):
    print(ans[i])

Submission status: Accepted

Solution code:
def getN():
    return int(input())
def getNM():
    return map(int, input().split())
def getList():
    return list(map(int, input().split()))
def getArray(intn):
    return [int(input()) for i in range(intn)]
def input():
    return sys.stdin.readline().rstrip()
def rand_N(ran1, ran2):
    return random.randint(ran1, ran2)
def rand_List(ran1, ran2, rantime):
    return [random.randint(ran1, ran2) for i in range(rantime)]
def rand_ints_nodup(ran1, ran2, rantime):
  ns = []
  while len(ns) < rantime:
    n = random.randint(ran1, ran2)
    if not n in ns:
      ns.append(n)
  return sorted(ns)

def rand_query(ran1, ran2, rantime):
  r_query = []
  while len(r_query) < rantime:
    n_q = rand_ints_nodup(ran1, ran2, 2)
    if not n_q in r_query:
      r_query.append(n_q)
  return sorted(r_query)

from collections import defaultdict, deque, Counter
from sys import exit
from decimal import *
import heapq
from math import sqrt
from fractions import gcd
import random
import string
import copy
from itertools import combinations, permutations, product
from operator import mul, itemgetter
from functools import reduce
from bisect import bisect_left, bisect_right

import sys
sys.setrecursionlimit(1000000000)
mod = 10 ** 9 + 7

#############
# Main Code #
#############

class BIT:
    def __init__(self, N):
        self.N = N
        self.bit = [0] * (N + 1)
        self.b = 1 << N.bit_length() - 1

    # a - 1の場所にwを追加する
    def add(self, a, w):
        x = a
        while(x <= self.N):
            self.bit[x] += w
            x += x & -x

    def get(self, a):
        ret, x = 0, a - 1
        while(x > 0):
            ret += self.bit[x]
            x -= x & -x
        return ret

    # 区間[l, r - 2]についての合計を求める
    def cum(self, l, r):
        return self.get(r) - self.get(l)

    def lowerbound(self,w):
        if w <= 0:
            return 0
        x = 0
        k = self.b
        while k > 0:
            if x + k <= self.N and self.bit[x + k] < w:
                w -= self.bit[x + k]
                x += k
            k //= 2
        return x + 1

# BITは前から置いていく
# そのためのクエリソート
N, Q = getNM()
C = getList()
que = [getList() for i in range(Q)]

# que[r]に[l(始点), i(queでのインデックス)]をappend
que_d = defaultdict(list)
for i in range(Q):
    que_d[que[i][1]].append([que[i][0], i])
ans = [0] * Q
# 色iのうち最も右側にあるものはどこにあるか
dic = defaultdict(lambda: -float('inf'))
bit = BIT(N)

for i in range(N):
    # 既に場所が登録されているならそれを削除する
    if dic[C[i]] >= 1:
        bit.add(dic[C[i]], -1)
    # 新しい「良い球」の場所を登録
    # 1-indexで!!
    dic[C[i]] = i + 1
    bit.add(dic[C[i]], 1)

    # queryに答える
    if len(que_d[i + 1]) > 0:
        # 終点rがi + 1であるqueryに答える
        for l, j in que_d[i + 1]:
            # cum(l, r):区間[l - 1, r - 2](0-index)についての合計を求める
            # lは1-indexだがi(r - 1)は0 - index
            ans[j] = bit.cum(l, i + 2)

for i in ans:
    print(i)

Submission status: Accepted

Solution code:
import numpy as np
def proc(C, L, R, Order, N, Q):
    pl = pr = 0
    ans = 0
    A = np.zeros(N+1, dtype=np.int32)
    Ans = np.zeros(Q, dtype=np.int32)
    for idx_LR in Order:
        l = L[idx_LR]
        r = R[idx_LR]
        while pr < r:
            pr += 1
            c = C[pr]
            if A[c] == 0:
                ans += 1
            A[c] += 1
        while pl > l:
            pl -= 1
            c = C[pl]
            if A[c] == 0:
                ans += 1
            A[c] += 1
        while pr > r:
            c = C[pr]
            A[c] -= 1
            if A[c] == 0:
                ans -= 1
            pr -= 1
        while pl < l:
            c = C[pl]
            A[c] -= 1
            if A[c] == 0:
                ans -= 1
            pl += 1
        Ans[idx_LR] = ans
    return Ans


numba_config = [
    ["proc", "i4[:](i4[:],u4[:],u4[:],i8[:],i4,i4)"]
]
import os
import sys
if sys.argv[-1] == "ONLINE_JUDGE":
    from numba.pycc import CC
    cc = CC("my_module")
    for func_name, types in numba_config:
        cc.export(func_name, types)(vars()[func_name])
        cc.compile()
    exit()
elif os.name == "posix":
    exec(f"from my_module import {','.join(func_name for func_name, _ in numba_config)}")
else:
    from numba import njit
    for func_name, types in numba_config:
        vars()[func_name] = njit(types, cache=True)(vars()[func_name])
    print("compiled", file=sys.stderr)


def main():
    input = sys.stdin.buffer.readline
    N, Q = map(int, input().split())
    C = np.empty(N+1, dtype=np.int32)
    C[0] = 0
    C[1:] = np.array(input().split(), dtype=np.int32)
    LR = np.array(sys.stdin.buffer.read().split(), dtype=np.uint32)
    L = LR[::2]
    R = LR[1::2]
    B = L>>9<<20|R
    Idx = (L>>9&1).astype(np.bool)
    B[Idx] = L[Idx]>>9<<20|(1<<20)-R[Idx]
    Order = np.argsort(B)
    Ans = proc(C, L, R, Order, N, Q)
    print("\n".join(map(str, Ans.tolist())))

main()

Submission status: Accepted

Solution code:
class BIT:
    """
    https://tjkendev.github.io/procon-library/python/range_query/bit.html
    """
    def __init__(self, n):
        self.n = n
        self.data = [0] * (n + 1)
        self.el = [0] * (n + 1)

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

    def add(self, i, x):
        assert i > 0
        self.el[i] += x
        while i <= self.n:
            self.data[i] += x
            i += i & -i

    def get(self, i, j=None):
        if j is None:
            return self.el[i]
        return self.sum(j) - self.sum(i)


def solve(n, q, c_list, lr_list):
    lri_list = [[lr_list[i][0], lr_list[i][1], i] for i in range(q)]
    # sort by r
    lri_list_s = sorted(lri_list, key=lambda x: x[1])
    # color_index
    color_index = [0] * (n + 1)
    # bit
    bit = BIT(n)

    res = [0] * q

    r_temp = 0
    for l, r, i in lri_list_s:
        while r > r_temp:
            r_temp += 1
            c = c_list[r_temp - 1]
            c_ind = color_index[c]
            if c_ind > 0:
                bit.add(c_ind, -1)
            color_index[c] = r_temp
            bit.add(r_temp, 1)
        # print(r, [bit.get(i) for i in range(n + 1)])
        res[i] = bit.get(l - 1, r)
    # print(res)
    return res


def main():
    n, q = map(int, input().split())
    c_list = list(map(int, input().split()))
    lr_list = [list(map(int, input().split())) for _ in range(q)]
    res = solve(n, q, c_list, lr_list)
    for r in res:
        print(r)


def test():
    assert solve(4, 3, [1, 2, 1, 3], [[1, 3], [2, 4], [3, 3]]) == [2, 3, 1]
    assert solve(10, 10, [2, 5, 6, 5, 2, 1, 7, 9, 7, 2], [
        [5, 5], [2, 4], [6, 7], [2, 2], [7, 8], [7, 9], [1, 8], [6, 9], [8, 10], [6, 8]
    ]) == [1, 2, 2, 1, 2, 2, 6, 3, 3, 3]


if __name__ == "__main__":
    test()
    main()

Submission status: Accepted

Solution code:
import sys

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline


class BIT:
    def __init__(self, n):
        self.n = n
        self.data = [0] * (n + 1)

    def add(self, i, x=1):
        i += 1
        while i <= self.n:
            self.data[i] += x
            i += i & -i

    def get_sum(self, i):
        i += 1
        x = 0
        while i > 0:
            x += self.data[i]
            i -= i & -i
        return x

    # Return sum for [l, r)
    def get_sum_range(self, l, r):
        return self.get_sum(r - 1) - self.get_sum(l - 1)


def main():
    N, Q = map(int, readline().split())
    C = list(map(int, readline().split()))
    LR = map(int, read().split())

    prev = [-1] * (N + 1)
    ps = [[] for _ in range(N)]
    for i, c in enumerate(C):
        if prev[c] != -1:
            ps[prev[c]].append(i)
        prev[c] = i

    qs = [[] for _ in range(N)]
    for i, (l, r) in enumerate(zip(*[iter(LR)] * 2)):
        qs[l - 1].append((r - 1, i))

    ans = [0] * Q
    bit = BIT(N)

    for l in range(N - 1, -1, -1):
        for r in ps[l]:
            bit.add(r)
        for r, i in qs[l]:
            ans[i] = (r - l + 1) - bit.get_sum(r)

    print('\n'.join(map(str, ans)), sep='\n')

    return


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys

read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines
sys.setrecursionlimit(10 ** 9)
INF = 1 << 60
MOD = 1000000007


class BIT:
    def __init__(self, n):
        self.n = n
        self.data = [0] * (n + 1)

    def add(self, i, x=1):
        i += 1
        while i <= self.n:
            self.data[i] += x
            i += i & -i

    def get_sum(self, i):
        i += 1
        x = 0
        while i > 0:
            x += self.data[i]
            i -= i & -i
        return x

    # Return sum for [l, r)
    def get_sum_range(self, l, r):
        return self.get_sum(r - 1) - self.get_sum(l - 1)


def main():
    N, Q = map(int, readline().split())
    C = list(map(int, readline().split()))
    LR = map(int, read().split())

    prev = [-1] * (N + 1)
    ps = [[] for _ in range(N)]
    for i, c in enumerate(C):
        if prev[c] != -1:
            ps[prev[c]].append(i)
        prev[c] = i

    qs = [[] for _ in range(N + 1)]
    for i, (l, r) in enumerate(zip(*[iter(LR)] * 2)):
        l -= 1
        r -= 1
        qs[l].append((r, i))

    ans = [0] * Q
    bit = BIT(N)

    for l in range(N - 1, -1, -1):
        for r in ps[l]:
            bit.add(r)
        for r, i in qs[l]:
            ans[i] = (r - l + 1) - bit.get_sum(r)

    print(*ans, sep='\n')

    return


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
SHIFT = 1 << 20


class fenwick_tree:
    """
    区間の一点更新と，区間和の取得がO(log n)で可能なデータ構造
    1-indexedで実装
    """

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

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

    def sum_acc(self, i, j):
        """ [i,j] の和を返す """
        return self.sum_until(j) - self.sum_until(i-1)

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


def main():
    N, Q = (int(i) for i in input().split())
    C = [int(i) for i in input().split()]
    Query = []
    for j in range(Q):
        le, ri = (int(i) for i in input().split())
        Query.append(ri << 40 | le << 20 | j)
    Query.sort()

    # Query復元
    for i in range(Q):
        j = Query[i] % (SHIFT)
        Query[i] >>= 20
        le = Query[i] % (SHIFT)
        Query[i] >>= 20
        ri = Query[i]
        Query[i] = (le, ri, j)
    Query.append((-1, -1, -1))

    lastappend = [-1] * (N + 1)
    bit = fenwick_tree(N)
    idx = 0  # Queryのindex
    ans = [0]*Q

    for i, a in enumerate(C, start=1):
        if lastappend[a] != -1:
            bit.add(lastappend[a], -1)
        lastappend[a] = i
        bit.add(i, 1)
        while i == Query[idx][1]:
            (le, ri, j) = Query[idx]
            ans[j] = bit.sum_acc(le, ri)
            idx += 1

    print(*ans, sep="\n")


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
SHIFT = 1 << 20


def main():
    N, Q = (int(i) for i in input().split())
    C = [int(i) for i in input().split()]
    Query = []
    for j in range(Q):
        le, ri = (int(i) for i in input().split())
        Query.append(ri << 40 | le << 20 | j)
    Query.sort()

    # Query復元
    for i in range(Q):
        j = Query[i] % (SHIFT)
        Query[i] >>= 20
        le = Query[i] % (SHIFT)
        Query[i] >>= 20
        ri = Query[i]
        Query[i] = (le, ri, j)
    Query.append((-1, -1, -1))

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

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

    lastappend = [-1] * (N + 1)
    bit = [0] * (N + 1)
    idx = 0  # Queryのindex
    ans = [0]*Q

    for i, a in enumerate(C, start=1):
        if lastappend[a] != -1:
            add(bit, lastappend[a], -1)
        lastappend[a] = i
        add(bit, i, 1)
        while i == Query[idx][1]:
            (le, ri, j) = Query[idx]
            ans[j] = sum(bit, ri) - sum(bit, le-1)
            idx += 1

    print(*ans, sep="\n")


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys
input = sys.stdin.readline


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

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

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


n, q = map(int, input().split())
*C, = map(lambda x: int(x) - 1, input().split())
P = [0] * n
N = [None] * n
for i in range(n)[::-1]:
    if P[C[i]]:
        N[i] = P[C[i]]
    P[C[i]] = i
F = [0] * n
B = BIT(n)
for i in range(n):
    if F[C[i]] == 0:
        B.add(i, 1)
        F[C[i]] = 1
XY = [tuple(map(int, input().split())) for j in range(q)]
ids = list(range(q))
ids.sort(key=lambda j: XY[j][0])
a = 0
lst = [0] * q
for j in ids:
    x, y = XY[j]
    for i in range(a, x - 1):
        if N[i]:
            B.add(N[i], 1)
    a = x - 1
    lst[j] = B.sum(y) - B.sum(x - 1)
print(*lst, sep="\n")

Submission status: Accepted

Solution code:
from collections import defaultdict
import sys
def read():
    return sys.stdin.readline().rstrip()
def main():
    N, Q = map(int, read().split())
    C = list(map(int, read().split()))
    E = defaultdict(list)

    D = [-1] * (N + 1)
    for i in range(N):
        D_i = D[C[i]]
        if D_i != -1:
            E[D_i].append((D_i, i))
        D[C[i]] = i

    F = defaultdict(list)
    for i in range(Q):
        l, r = map(int, input().split())
        F[l-1].append((r - 1, i))



    # Binary Indexed Tree (Fenwick Tree)
    class BIT:
        def __init__(self, n):
            self.n = n
            self.data = [0] * (n + 1)
            self.el = [0] * (n + 1)

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

        def add(self, i, x):
            # assert i > 0
            self.el[i] += x
            while i <= self.n:
                self.data[i] += x
                i += i & -i

        def get(self, i, j=None):
            if j is None:
                return self.el[i]
            return self.sum(j) - self.sum(i)

    ANS = [0] * Q
    d = BIT(N)
    for x in range(N - 1, -1, -1):
        for e in E[x]:
            d.add(e[1], 1)
        for f in F[x]:
            ANS[f[1]] = f[0] - x + 1 - d.sum(f[0])

    for i in range(Q):
        print(ANS[i])

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
n,q=map(int,input().split())
N=n

data = [0]*(N+1)
def add(k, x):
    while k <= N:
        data[k] += x
        k += k & -k

def get(k):
    s = 0
    while k:
        s += data[k]
        k -= k & -k
    return s

c=[int(i) for i in input().split()]
Q=[]
for i in range(q):
    l,r=map(int,input().split())
    Q.append((l,r,i))
Ans=[0 for i in range(q)]
F=[-1 for i in range(5*10**5+1)]
Q.sort(key=lambda x:x[1])
#Q.append((10**6,10**6,10**6))

for i in range(n):
    add(i+1,1)

"""
quen=0
nowQ=Q[quen]
for i in range(n):
    ci=c[i]
    if F[ci]>=0:
        add(F[ci]+1,-1)
    F[ci]=i
    while nowQ[1]==i+1:
        Ans[nowQ[2]]=-get(nowQ[0]-1)+get(nowQ[1])
        quen+=1
        nowQ=Q[quen]
    if nowQ[1]==10**6:
        break
"""

i=0
for nowQ in Q:
    while nowQ[1]!=i:
        ci=c[i]
        if F[ci]>=0:
            add(F[ci]+1,-1)
        F[ci]=i
        i+=1
    Ans[nowQ[2]]=-get(nowQ[0]-1)+get(nowQ[1])


print("\n".join([str(i) for i in Ans]))

Submission status: Accepted

Solution code:
import sys
def input(): return sys.stdin.readline().strip()
def mapint(): return map(int, input().split())
sys.setrecursionlimit(10**9)

N, Q = mapint()
Cs = list(mapint())
LR = []
for i in range(Q):
    l, r = mapint()
    k = (r<<40)+(l<<20)+i
    LR.append(k)
LR.sort()
mask = (1<<20)-1
A = [0]*N

def add(A,a,w):#リストに値を追加する関数
    x = a
    while x <= N:
        A[x-1] += w
        x += x&(-x)

def sums(A,a):#k番目までの和
    x = a
    S = 0
    while x != 0:
        S += A[x-1]
        x -= x&(-x)
    return S

ans = [0]*Q
i = 0
last_appeared = [-1]*(N+1)
for k in LR:
    ans_idx = k&mask
    l = (k>>20)&mask
    r = (k>>40)
    while i<r:
        c = Cs[i]
        if last_appeared[c]==-1:
            last_appeared[c] = i+1
            add(A, i+1, 1)
        else:
            past = last_appeared[c]
            last_appeared[c] = i+1
            add(A, past, -1)
            add(A, i+1, 1)
        i += 1
    ans[ans_idx] = sums(A, r)-sums(A, l-1)
for a in ans:
    print(a)

Submission status: Accepted

Solution code:
import sys
def input(): return sys.stdin.readline().strip()
def mapint(): return map(int, input().split())
sys.setrecursionlimit(10**9)

N, Q = mapint()
Cs = list(mapint())
LR = []
for i in range(Q):
    l, r = mapint()
    k = r*(10**12)+l*(10**6)+i
    LR.append(k)
LR.sort()
A = [0]*N

def add(A,a,w):#リストに値を追加する関数
    x = a
    while x <= N:
        A[x-1] += w
        x += x&(-x)

def sums(A,a):#k番目までの和
    x = a
    S = 0
    while x != 0:
        S += A[x-1]
        x -= x&(-x)
    return S

ans = [0]*Q
i = 0
last_appeared = [-1]*(N+1)
for k in LR:
    ans_idx = k%(10**6)
    l = k//(10**6)%(10**6)
    r = k//(10**12)
    while i<r:
        c = Cs[i]
        if last_appeared[c]==-1:
            last_appeared[c] = i+1
            add(A, i+1, 1)
        else:
            past = last_appeared[c]
            last_appeared[c] = i+1
            add(A, past, -1)
            add(A, i+1, 1)
        i += 1
    ans[ans_idx] = sums(A, r)-sums(A, l-1)
for a in ans:
    print(a)

Submission status: Accepted

Solution code:
import sys
def input(): return sys.stdin.readline().strip()
def mapint(): return map(int, input().split())
sys.setrecursionlimit(10**9)

N, Q = mapint()
Cs = list(mapint())
LR = []
for i in range(Q):
    l, r = mapint()
    LR.append((l, r, i))
LR.sort(key=lambda x:x[1])
A = [0]*N

def add(A,a,w):#リストに値を追加する関数
    x = a
    while x <= N:
        A[x-1] += w
        x += x&(-x)

def sums(A,a):#k番目までの和
    x = a
    S = 0
    while x != 0:
        S += A[x-1]
        x -= x&(-x)
    return S

ans = [0]*Q
i = 0
last_appeared = [-1]*(N+1)
for l, r, ans_idx in LR:
    while i<r:
        c = Cs[i]
        if last_appeared[c]==-1:
            last_appeared[c] = i+1
            add(A, i+1, 1)
        else:
            past = last_appeared[c]
            last_appeared[c] = i+1
            add(A, past, -1)
            add(A, i+1, 1)
        i += 1
    ans[ans_idx] = sums(A, r)-sums(A, l-1)
for a in ans:
    print(a)

Submission status: Accepted

Solution code:
import sys
def input(): return sys.stdin.readline().strip()
def mapint(): return map(int, input().split())
sys.setrecursionlimit(10**9)

N, Q = mapint()
Cs = list(mapint())
LR = []
for i in range(Q):
    l, r = mapint()
    LR.append((l, r, i))
LR.sort(key=lambda x:x[1])
A = [0]*N

def add(A,a,w):#リストに値を追加する関数
    x = a
    while x <= N:
        A[x-1] += w
        x += x&(-x)

def sums(A,a):#k番目までの和
    x = a
    S = 0
    while x != 0:
        S += A[x-1]
        x -= x&(-x)
    return S

ans = [0]*Q
idx = 0
dic = {}
for i in range(N):
    c = Cs[i]
    if c not in dic:
        dic[c] = i+1
        add(A, i+1, 1)
    else:
        past = dic[c]
        dic[c] = i+1
        add(A, past, -1)
        add(A, i+1, 1)
    while idx<Q and LR[idx][1]<=i+1:
        l, r, ans_idx = LR[idx]
        ans[ans_idx] = sums(A, r)-sums(A, l-1)
        idx += 1
for a in ans:
    print(a)