Hossam and Range Minimum Query (Codeforces 1771F)
Tags: Others, hashing

Hossam gives you a sequence of integers $$$a_1, \, a_2, \, \dots, \, a_n$$$ of length $$$n$$$. Moreover, he will give you $$$q$$$ queries of type $$$(l, \, r)$$$. For each query, consider the elements $$$a_l, \, a_{l + 1}, \, \dots, \, a_r$$$. Hossam wants to know the smallest number in this sequence, such that it occurs in this sequence an odd number of times.You need to compute the answer for each query before process the next query.

Input: The first line of the input contains one integer $$$n$$$ ($$$1 \le n \le 2 \cdot 10^5$$$), the length of the sequence.The second line contains $$$n$$$ integers $$$a_1, \, a_2, \, \dots, \, a_n$$$ ($$$1 \le a_i \le 10^9$$$).The third line contains one integer $$$q$$$ ($$$1 \le q \le 2 \cdot 10^5$$$), the number of queries.Each of the next $$$q$$$ lines contains two integers $$$a$$$ and $$$b$$$ ($$$0 \le a, \, b \le 2 \cdot 10^9$$$), the numbers used to encode the queries. Let $$$\mathrm{ans}_i$$$ be the answer on the $$$i$$$-th query, and $$$\mathrm{ans}_0$$$ be zero. Then $$$$$$l_i = a_i \oplus \mathrm{ans}_{i - 1},$$$$$$ $$$$$$r_i = b_i \oplus \mathrm{ans}_{i - 1},$$$$$$ where $$$l_i, \, r_i$$$ are parameters of the $$$i$$$-th query and $$$\oplus$$$ means the bitwise exclusive or operation. It is guaranteed that $$$1 \le l \le r \le n$$$.

Output: For each query, print the smallest number that occurs an odd number of times on the given segment of the sequence.If there is no such number, print $$$0$$$.

Note: In the example,$$$$$$l_1 = 1, \, r_1 = 2,$$$$$$ $$$$$$l_2 = 1, \, r_2 = 3,$$$$$$ $$$$$$l_3 = 2, \, r_3 = 4,$$$$$$ $$$$$$l_4 = 1, \, r_4 = 4,$$$$$$ $$$$$$l_5 = 2, \, r_5 = 2,$$$$$$ $$$$$$l_6 = 1, \, r_6 = 5.$$$$$$

Sample Inputs:
5
1 2 1 2 2
6
1 2
0 2
0 6
0 5
2 2
3 7

10
51 43 69 48 23 52 48 76 19 55
10
1 1
57 57
54 62
20 27
56 56
79 69
16 21
18 30
25 25
62 61

Sample Outputs:
1
2
1
0
2
2

51
55
19
48
76
19
23
19
55
19

Solution (Python):
from collections import defaultdict
import random
import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def f(u, v):
    return u * m0 + v

def get_min(s, t):
    (s, t) = (s + l1, t + l1)
    ans = inf
    while s <= t:
        if s & 1:
            ans = min(ans, tree[s])
            s += 1
        s >>= 1
        if not t & 1:
            ans = min(ans, tree[t])
            t -= 1
        t >>= 1
    return ans
n = int(input())
a = [0] + list(map(int, input().split()))
r = random.randint(1, pow(2, 30) - 1)
cnt = defaultdict(lambda : 0)
for i in a:
    cnt[i ^ r] += 1
l1 = pow(2, (n + 1).bit_length())
l2 = 2 * l1
inf = 2 * pow(10, 9) + 1
tree = [inf] * l2
(l0, r0, b, c) = ([inf] * (n + 1), [-inf] * (n + 1), [0], 1)
for i in range(1, n + 1):
    if cnt[a[i] ^ r] == 1:
        tree[i + l1] = a[i]
    else:
        (l0[i], r0[i]) = (c, c)
        b.append(a[i])
        c += 1
for i in range(n - 1, 0, -1):
    l0[i] = min(l0[i], l0[i + 1])
for i in range(2, n + 1):
    r0[i] = max(r0[i], r0[i - 1])
for i in range(l1 - 1, 0, -1):
    tree[i] = min(tree[2 * i], tree[2 * i + 1])
n = len(b) - 1
(u, d) = ([], dict())
for i in cnt:
    if cnt[i] ^ 1:
        u.append(i ^ r)
u.sort()
m = len(u)
for i in range(m):
    d[u[i]] = i
z = 7000
pow2 = [1]
for _ in range(z - 1):
    pow2.append(2 * pow2[-1])
m0 = m // z + min(m % z, 1)
now = [0] * m0
(la, nx) = ([0] * m0, [inf] * (n + 1))
(f0, c) = ([inf] * m0, [0] * (n + 1))
s = [0] * (((n + 1) // 16 + 1) * m0)
for i in range(1, n + 1):
    (x, y) = divmod(d[b[i]], z)
    now[x] ^= pow2[z - y - 1]
    c[i] = now[x]
    if la[x]:
        nx[la[x]] = i
    la[x] = i
    f0[x] = min(f0[x], i)
    if not i % 16:
        k = i >> 4
        for j in range(m0):
            s[f(k, j)] = la[j]
q = int(input())
ans = []
ans0 = 0
for _ in range(q):
    (a0, b0) = map(int, input().split())
    (l, r) = (a0 ^ ans0, b0 ^ ans0)
    ans0 = get_min(l, r)
    (l, r) = (l0[l], r0[r])
    if l <= r:
        (ll0, rr0) = (l - 1 >> 4, r >> 4)
        for i in range(m0):
            if ans0 < u[i * z]:
                break
            (ll, rr) = (s[f(ll0, i)], s[f(rr0, i)])
            (nl, nr) = (nx[ll] if ll else f0[i], nx[rr] if rr else f0[i])
            while nl <= l - 1:
                (ll, nl) = (nl, nx[nl])
            while nr <= r:
                (rr, nr) = (nr, nx[nr])
            if c[ll] ^ c[rr]:
                ans0 = min(ans0, u[i * z + z - (c[ll] ^ c[rr]).bit_length()])
                break
    ans0 %= inf
    ans.append(ans0)
sys.stdout.write('\n'.join(map(str, ans)))

Solution (Python):
import random
import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline

def get_min(s, t):
    (s, t) = (s ^ l1, t ^ l1)
    ans = inf
    while s <= t:
        if s & 1:
            ans = min(ans, mi[s])
            s += 1
        s >>= 1
        if not t & 1:
            ans = min(ans, mi[t])
            t -= 1
        t >>= 1
    return ans
n = int(input())
inf = pow(10, 9) + 1
a = [0] + list(map(int, input().split())) + [inf]
u = list(a)
u.sort()
(s, x) = (set(), [])
for i in range(1, n + 1):
    if u[i - 1] < u[i] < u[i + 1]:
        s.add(u[i])
    elif u[i - 1] < u[i] == u[i + 1]:
        x.append(u[i])
y = []
l1 = pow(2, (n + 1).bit_length())
l2 = 2 * l1
mi = [inf] * l2
for i in range(1, n + 1):
    if a[i] in s:
        mi[i ^ l1] = a[i]
    else:
        y.append(i)
for i in range(l1 - 1, 0, -1):
    mi[i] = min(mi[2 * i], mi[2 * i + 1])
m = len(x)
d = dict()
for i in range(m):
    d[x[i]] = i
rr = [random.randint(1, 1 << 60) for _ in range(m)]
l3 = pow(2, (m + 1).bit_length())
l4 = 2 * l3
s0 = [1] * (l4 + 3)
s0[0] = s0[1] = 0
for i in y:
    a[i] = d[a[i]]
    j = a[i] ^ l3
    while j:
        s0[j + 2] += 1
        j >>= 1
for i in range(3, l4 + 3):
    s0[i] += s0[i - 1]
tree = [0] * s0[-1]
s1 = [0] * s0[-1]
for i in y:
    (j, h) = (a[i] ^ l3, rr[a[i]])
    while j:
        k = s0[j + 1]
        (tree[k], s1[k]) = (tree[k - 1] ^ h, i)
        s0[j + 1] += 1
        j >>= 1
u = [0] * (n + 1)
for i in range(s0[1], s0[2]):
    h = tree[i]
    for j in range(s1[i], s1[i + 1] if s1[i + 1] else n + 1):
        u[j] = h
q = int(input())
(ans, ans0) = ([], 0)
for _ in range(q):
    (a, b) = map(int, input().split())
    (l, r) = (a ^ ans0, b ^ ans0)
    ans0 = get_min(l, r)
    if u[l - 1] ^ u[r]:
        i = 1
        while not i & l3:
            (l0, r0) = (s0[2 * i], s0[2 * i + 1])
            p = pow(2, (r0 - l0).bit_length() - 1)
            (j, k) = (l0, l0)
            while p:
                if j + p < r0 and s1[j + p] <= l - 1:
                    j += p
                if k + p < r0 and s1[k + p] <= r:
                    k += p
                p >>= 1
            i = 2 * i if tree[j] ^ tree[k] else 2 * i + 1
        ans0 = min(ans0, x[i ^ l3])
    ans0 %= inf
    ans.append(str(ans0))
sys.stdout.write('\n'.join(ans))

Solution (Python):
import random
import sys, os, io
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
n = int(input())
inf = pow(10, 9) + 1
a = [0] + list(map(int, input().split()))
x = list(sorted(a[1:]))
m = len(x)
d = dict()
for i in range(m):
    d[x[i]] = i
rr = [random.randint(1, 1 << 60) for _ in range(m)]
l1 = pow(2, (m + 1).bit_length())
l2 = 2 * l1
s0 = [1] * (l2 + 3)
s0[0] = s0[1] = 0
for i in range(1, n + 1):
    a[i] = d[a[i]]
    j = a[i] ^ l1
    while j:
        s0[j + 2] += 1
        j >>= 1
for i in range(3, l2 + 3):
    s0[i] += s0[i - 1]
tree = [0] * s0[-1]
s1 = [0] * s0[-1]
for i in range(1, n + 1):
    (j, h) = (a[i] ^ l1, rr[a[i]])
    while j:
        k = s0[j + 1]
        (tree[k], s1[k]) = (tree[k - 1] ^ h, i)
        s0[j + 1] += 1
        j >>= 1
u = [0] * (n + 1)
for i in range(s0[1], s0[2]):
    h = tree[i]
    for j in range(s1[i], s1[i + 1] if s1[i + 1] else n + 1):
        u[j] = h
q = int(input())
(ans, ans0) = ([], 0)
for _ in range(q):
    (a, b) = map(int, input().split())
    (l, r) = (a ^ ans0, b ^ ans0)
    ans0 = 0
    if u[l - 1] ^ u[r]:
        i = 1
        while not i & l1:
            (l0, r0) = (s0[2 * i], s0[2 * i + 1])
            p = pow(2, (r0 - l0).bit_length() - 1)
            (j, k) = (l0, l0)
            while p:
                if j + p < r0 and s1[j + p] <= l - 1:
                    j += p
                if k + p < r0 and s1[k + p] <= r:
                    k += p
                p >>= 1
            i = 2 * i if tree[j] ^ tree[k] else 2 * i + 1
        ans0 = x[i ^ l1]
    ans.append(str(ans0))
sys.stdout.write('\n'.join(ans))