Recently Lynyrd and Skynyrd went to a shop where Lynyrd bought a permutation $p$ of length $n$, and Skynyrd bought an array $a$ of length $m$, consisting of integers from $1$ to $n$. 

Lynyrd and Skynyrd became bored, so they asked you $q$ queries, each of which has the following form: "does the subsegment of $a$ from the $l$-th to the $r$-th positions, inclusive, have a subsequence that is a cyclic shift of $p$?" Please answer the queries.

A permutation of length $n$ is a sequence of $n$ integers such that each integer from $1$ to $n$ appears exactly once in it.

A cyclic shift of a permutation $(p_1, p_2, \ldots, p_n)$ is a permutation $(p_i, p_{i + 1}, \ldots, p_{n}, p_1, p_2, \ldots, p_{i - 1})$ for some $i$ from $1$ to $n$. For example, a permutation $(2, 1, 3)$ has three distinct cyclic shifts: $(2, 1, 3)$, $(1, 3, 2)$, $(3, 2, 1)$.

A subsequence of a subsegment of array $a$ from the $l$-th to the $r$-th positions, inclusive, is a sequence $a_{i_1}, a_{i_2}, \ldots, a_{i_k}$ for some $i_1, i_2, \ldots, i_k$ such that $l \leq i_1 < i_2 < \ldots < i_k \leq r$.


-----Input-----

The first line contains three integers $n$, $m$, $q$ ($1 \le n, m, q \le 2 \cdot 10^5$) — the length of the permutation $p$, the length of the array $a$ and the number of queries.

The next line contains $n$ integers from $1$ to $n$, where the $i$-th of them is the $i$-th element of the permutation. Each integer from $1$ to $n$ appears exactly once.

The next line contains $m$ integers from $1$ to $n$, the $i$-th of them is the $i$-th element of the array $a$.

The next $q$ lines describe queries. The $i$-th of these lines contains two integers $l_i$ and $r_i$ ($1 \le l_i \le r_i \le m$), meaning that the $i$-th query is about the subsegment of the array from the $l_i$-th to the $r_i$-th positions, inclusive.


-----Output-----

Print a single string of length $q$, consisting of $0$ and $1$, the digit on the $i$-th positions should be $1$, if the subsegment of array $a$ from the $l_i$-th to the $r_i$-th positions, inclusive, contains a subsequence that is a cyclic shift of $p$, and $0$ otherwise.


-----Examples-----
Input
3 6 3
2 1 3
1 2 3 1 2 3
1 5
2 6
3 5

Output
110

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

Output
010



-----Note-----

In the first example the segment from the $1$-st to the $5$-th positions is $1, 2, 3, 1, 2$. There is a subsequence $1, 3, 2$ that is a cyclic shift of the permutation. The subsegment from the $2$-nd to the $6$-th positions also contains a subsequence $2, 1, 3$ that is equal to the permutation. The subsegment from the $3$-rd to the $5$-th positions is $3, 1, 2$, there is only one subsequence of length $3$ ($3, 1, 2$), but it is not a cyclic shift of the permutation.

In the second example the possible cyclic shifts are $1, 2$ and $2, 1$. The subsegment from the $1$-st to the $2$-nd positions is $1, 1$, its subsequences are not cyclic shifts of the permutation. The subsegment from the $2$-nd to the $3$-rd positions is $1, 2$, it coincides with the permutation. The subsegment from the $3$ to the $4$ positions is $2, 2$, its subsequences are not cyclic shifts of the permutation.

Source: codeforces | Difficulty: HARD
Tags: Graph traversal

Tree algorithms

Dynamic programming

Mathematics

Data structures


Solutions:
import sys

class segmentTree:

	def __init__(self, n):
		self.n = n
		self.seg = [self.n + 1] * (self.n << 1)

	def update(self, p, value):
		p += self.n
		self.seg[p] = value
		while p > 1:
			p >>= 1
			self.seg[p] = min(self.seg[p * 2], self.seg[p * 2 + 1])

	def query(self, l, r):
		res = self.n
		l += self.n
		r += self.n
		while l < r:
			if l & 1:
				res = min(res, self.seg[l])
				l += 1
			if r & 1:
				res = min(res, self.seg[r - 1])
				r -= 1
			l >>= 1
			r >>= 1
		return res
inp = [int(x) for x in sys.stdin.read().split()]
(n, m, q) = (inp[0], inp[1], inp[2])
p = [inp[idx] for idx in range(3, n + 3)]
index_arr = [0] * (n + 1)
for i in range(n):
	index_arr[p[i]] = i
a = [inp[idx] for idx in range(n + 3, n + 3 + m)]
leftmost_pos = [m] * (n + 1)
next = [-1] * m
for i in range(m - 1, -1, -1):
	index = index_arr[a[i]]
	right_index = 0 if index == n - 1 else index + 1
	right = p[right_index]
	next[i] = leftmost_pos[right]
	leftmost_pos[a[i]] = i
log = 0
while 1 << log <= n:
	log += 1
log += 1
dp = [[m for _ in range(m + 1)] for _ in range(log)]
for i in range(m):
	dp[0][i] = next[i]
for j in range(1, log):
	for i in range(m):
		dp[j][i] = dp[j - 1][dp[j - 1][i]]
tree = segmentTree(m)
for i in range(m):
	p = i
	len = n - 1
	for j in range(log - 1, -1, -1):
		if 1 << j <= len:
			p = dp[j][p]
			len -= 1 << j
	tree.update(i, p)
inp_idx = n + m + 3
ans = []
for i in range(q):
	(l, r) = (inp[inp_idx] - 1, inp[inp_idx + 1] - 1)
	inp_idx += 2
	if tree.query(l, r + 1) <= r:
		ans.append('1')
	else:
		ans.append('0')
print(''.join(ans))


import sys
(N, M, Q) = map(int, sys.stdin.readline().split())
P = list(map(int, sys.stdin.readline().split()))
A = list(map(int, sys.stdin.readline().split()))
k = N.bit_length()
bef = [-2] * (N + 1)
for (p, q) in zip(P[1:] + [P[0]], P):
	bef[p] = q
recentapp = [-1] * (N + 1)
prepoints = [[-1] * (M + 2) for _ in range(k)]
for (i, a) in enumerate(A, 1):
	prepoints[0][i] = recentapp[bef[a]]
	recentapp[a] = i
for dim in range(1, k):
	for i in range(1, M + 1):
		prepoints[dim][i] = prepoints[dim - 1][prepoints[dim - 1][i]]
use = [i for i in range(k) if 1 & N - 1 >> i]
ran = [-1] * (M + 2)
maxpre = -1
for i in range(1, M + 1):
	t = i
	for dim in use:
		t = prepoints[dim][t]
	maxpre = max(maxpre, t)
	ran[i] = maxpre
Ans = [None] * Q
for q in range(Q):
	(l, r) = map(int, sys.stdin.readline().split())
	Ans[q] = str(int(l <= ran[r]))
print(''.join(Ans))


from math import log, floor
import sys

class RMQ:

	def __init__(self, nums):
		size = floor(log(len(nums)) // log(2)) + 1
		self.nums = [nums]
		for i in range(1, size):
			last = self.nums[-1]
			delta = 1 << i - 1
			self.nums.append([max(last[j], last[j + delta]) for j in range(len(nums) - 2 * delta + 1)])

	def query(self, l, r):
		delta = floor(log(r - l + 1) // log(2))
		return max(self.nums[delta][l], self.nums[delta][r - 2 ** delta + 1])
(n, m, q) = list(map(int, sys.stdin.readline().split()))
perms = list(map(int, sys.stdin.readline().split()))
nums = list(map(int, sys.stdin.readline().split()))
logit = floor(log(n) // log(2)) + 1
current_max_index = [-1] * (n + 1)
prevs = [[-1] * m for i in range(logit)]
prev_map = {perms[i]: perms[i - 1] for i in range(n)}
for (idx, ele) in enumerate(nums):
	prevs[0][idx] = current_max_index[prev_map[ele]]
	current_max_index[ele] = idx
for i in range(1, logit):
	for (idx, ele) in enumerate(nums):
		if prevs[i - 1][idx] != -1:
			prevs[i][idx] = prevs[i - 1][prevs[i - 1][idx]]
prev_n = []
for i in range(m):
	remain = n - 1
	idx = i
	while remain and idx != -1:
		ma = floor(log(remain) // log(2))
		idx = prevs[ma][idx]
		remain -= 2 ** ma
	prev_n.append(idx)
rmq = RMQ(prev_n)
ans = []
for i in range(q):
	(l, r) = list(map(int, sys.stdin.readline().split()))
	if rmq.query(l - 1, r - 1) >= l - 1:
		ans.append('1')
	else:
		ans.append('0')
print(''.join(ans))


from math import log, floor
import sys
(n, m, q) = map(int, sys.stdin.readline().split())
perms = list(map(int, sys.stdin.readline().split()))
nums = list(map(int, sys.stdin.readline().split()))
logit = floor(log(n) // log(2)) + 1
current_max_index = [-1] * (n + 1)
prevs = [[-1] * m for i in range(logit)]
prev_map = [-2] * (n + 1)
for (i, j) in zip(perms[1:] + [perms[0]], perms):
	prev_map[i] = j
for (idx, ele) in enumerate(nums):
	prevs[0][idx] = current_max_index[prev_map[ele]]
	current_max_index[ele] = idx
for i in range(1, logit):
	for (idx, ele) in enumerate(nums):
		if prevs[i - 1][idx] != -1:
			prevs[i][idx] = prevs[i - 1][prevs[i - 1][idx]]
prev_n = []
use = [i for i in range(n.bit_length()) if 1 & n - 1 >> i]
max_pre = -1
ran = [-1] * (m + 2)
for i in range(m):
	t = i
	for dim in use:
		t = prevs[dim][t]
		if t == -1:
			break
	max_pre = max(t, max_pre)
	ran[i] = max_pre
ans = [None] * q
for i in range(q):
	(l, r) = map(int, sys.stdin.readline().split())
	ans[i] = str(int(l - 1 <= ran[r - 1]))
print(''.join(ans))


import sys
inp = [int(x) for x in sys.stdin.read().split()]
(n, m, q) = (inp[0], inp[1], inp[2])
p = [inp[idx] for idx in range(3, n + 3)]
index_arr = [0] * (n + 1)
for i in range(n):
	index_arr[p[i]] = i
a = [inp[idx] for idx in range(n + 3, n + 3 + m)]
leftmost_pos = [m] * (n + 1)
next = [-1] * m
for i in range(m - 1, -1, -1):
	index = index_arr[a[i]]
	right_index = 0 if index == n - 1 else index + 1
	right = p[right_index]
	next[i] = leftmost_pos[right]
	leftmost_pos[a[i]] = i
log = 0
while 1 << log <= n:
	log += 1
log += 1
dp = [[m for _ in range(m + 1)] for _ in range(log)]
for i in range(m):
	dp[0][i] = next[i]
for j in range(1, log):
	for i in range(m):
		dp[j][i] = dp[j - 1][dp[j - 1][i]]
last = [0] * m
for i in range(m):
	p = i
	len = n - 1
	for j in range(log - 1, -1, -1):
		if 1 << j <= len:
			p = dp[j][p]
			len -= 1 << j
	last[i] = p
for i in range(m - 2, -1, -1):
	last[i] = min(last[i], last[i + 1])
inp_idx = n + m + 3
ans = []
for i in range(q):
	(l, r) = (inp[inp_idx] - 1, inp[inp_idx + 1] - 1)
	inp_idx += 2
	if last[l] <= r:
		ans.append('1')
	else:
		ans.append('0')
print(''.join(ans))


from math import log, floor

class RMQ:

	def __init__(self, nums):
		size = floor(log(len(nums)) // log(2)) + 1
		self.nums = [nums]
		for i in range(1, size):
			last = self.nums[-1]
			delta = 1 << i - 1
			self.nums.append([max(last[j], last[j + delta]) for j in range(len(nums) - 2 * delta + 1)])

	def query(self, l, r):
		delta = floor(log(r - l + 1) // log(2))
		return max(self.nums[delta][l], self.nums[delta][r - 2 ** delta + 1])
(n, m, q) = map(int, input().split())
perms = list(map(int, input().split()))
nums = list(map(int, input().split()))
logit = floor(log(n) // log(2)) + 1
current_max_index = [-1] * (n + 1)
prevs = [[-1] * m for i in range(logit)]
prev_map = [-2] * (n + 1)
for (i, j) in zip(perms[1:] + [perms[0]], perms):
	prev_map[i] = j
for (idx, ele) in enumerate(nums):
	prevs[0][idx] = current_max_index[prev_map[ele]]
	current_max_index[ele] = idx
for i in range(1, logit):
	for (idx, ele) in enumerate(nums):
		if prevs[i - 1][idx] != -1:
			prevs[i][idx] = prevs[i - 1][prevs[i - 1][idx]]
prev_n = []
use = [i for i in range(n.bit_length()) if 1 & n - 1 >> i]
max_pre = -1
ran = [-1] * (m + 2)
for i in range(m):
	t = i
	for dim in use:
		t = prevs[dim][t]
		if t == -1:
			break
	max_pre = max(t, max_pre)
	ran[i] = max_pre
ans = []
for i in range(q):
	(l, r) = map(int, input().split())
	if ran[r - 1] >= l - 1:
		ans.append('1')
	else:
		ans.append('0')
print(''.join(ans))


import os
from io import BytesIO, StringIO
input = BytesIO(os.read(0, os.fstat(0).st_size)).readline

def input_as_list():
	return list(map(int, input().split()))

def array_of(f, *dim):
	return [array_of(f, *dim[1:]) for _ in range(dim[0])] if dim else f()

def main():
	(n, m, q) = input_as_list()
	p = input_as_list()
	a = input_as_list()
	if n == 1:
		print('1' * q)
		return
	next_p = array_of(int, n)
	next_a = array_of(int, m)
	prev = p[-1] - 1
	for pi in p:
		pi -= 1
		next_p[prev] = pi
		prev = pi
	idx_a = array_of(int, n)
	for i in range(len(a) - 1, -1, -1):
		ai = a[i] - 1
		next_a[i] = idx_a[next_p[ai]]
		idx_a[ai] = i
	ep = array_of(int, m)
	parent = next_a
	children = array_of(list, m)
	roots = []
	for (i, p) in enumerate(parent):
		if p == 0:
			roots.append(i)
		else:
			children[p].append(i)
	rank = array_of(int, m)
	parent_ex = array_of(list, m)
	for r in roots:
		stack = [r]
		while stack:
			p = stack.pop()
			for c in children[p]:
				rank[c] = rank[p] + 1
				parent_ex[c].append(p)
				i = 1
				while 2 ** i <= rank[c]:
					parent_ex[c].append(parent_ex[parent_ex[c][-1]][i - 1])
					i += 1
				stack.append(c)
	for i in range(m):
		y = i
		s = 0
		try:
			for j in reversed(range(20)):
				if n - s - 1 >= 2 ** j:
					y = parent_ex[y][j]
					s += 2 ** j
			ep[i] = y
		except IndexError:
			pass
	mn = 200000
	flag = False
	for i in range(len(ep) - 1, -1, -1):
		epi = ep[i]
		if epi != 0:
			if epi > mn:
				ep[i] = mn
			mn = min(mn, epi)
			flag = True
		elif flag:
			ep[i] = mn
	out = []
	for _ in range(q):
		(l, r) = map(int, input().split())
		(l, r) = (l - 1, r - 1)
		if ep[l] == 0 or ep[l] > r:
			out.append('0')
		else:
			out.append('1')
	print(''.join(out))
main()