E. Lynyrd Skynyrd
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Recently Lynyrd and Skynyrd went to a shop where Lynyrd bought a permutation pp of length nn, and Skynyrd bought an array aa of length mm, consisting of integers from 11 to nn.
Lynyrd and Skynyrd became bored, so they asked you qq queries, each of which has the following form: "does the subsegment of aa from the ll-th to the rr-th positions, inclusive, have a subsequence that is a cyclic shift of pp?" Please answer the queries.
A permutation of length nn is a sequence of nn integers such that each integer from 11 to nn appears exactly once in it.
A cyclic shift of a permutation (p1,p2,…,pn)(p1,p2,…,pn) is a permutation (pi,pi+1,…,pn,p1,p2,…,pi−1)(pi,pi+1,…,pn,p1,p2,…,pi−1) for some ii from 11 to nn. For example, a permutation (2,1,3)(2,1,3) has three distinct cyclic shifts: (2,1,3)(2,1,3), (1,3,2)(1,3,2), (3,2,1)(3,2,1).
A subsequence of a subsegment of array aa from the ll-th to the rr-th positions, inclusive, is a sequence ai1,ai2,…,aikai1,ai2,…,aik for some i1,i2,…,iki1,i2,…,ik such that l≤i1<i2<…<ik≤rl≤i1<i2<…<ik≤r.
Input
The first line contains three integers nn, mm, qq (1≤n,m,q≤2⋅1051≤n,m,q≤2⋅105) — the length of the permutation pp, the length of the array aa and the number of queries.
The next line contains nn integers from 11 to nn, where the ii-th of them is the ii-th element of the permutation. Each integer from 11 to nnappears exactly once.
The next line contains mm integers from 11 to nn, the ii-th of them is the ii-th element of the array aa.
The next qq lines describe queries. The ii-th of these lines contains two integers lili and riri (1≤li≤ri≤m1≤li≤ri≤m), meaning that the ii-th query is about the subsegment of the array from the lili-th to the riri-th positions, inclusive.
Output
Print a single string of length qq, consisting of 00 and 11, the digit on the ii-th positions should be 11, if the subsegment of array aa from the lili-th to the riri-th positions, inclusive, contains a subsequence that is a cyclic shift of pp, and 00 otherwise.
Examples
input
Copy
3 6 3 2 1 3 1 2 3 1 2 3 1 5 2 6 3 5
output
Copy
110
input
Copy
2 4 3 2 1 1 1 2 2 1 2 2 3 3 4
output
Copy
010
Note
In the first example the segment from the 11-st to the 55-th positions is 1,2,3,1,21,2,3,1,2. There is a subsequence 1,3,21,3,2 that is a cyclic shift of the permutation. The subsegment from the 22-nd to the 66-th positions also contains a subsequence 2,1,32,1,3 that is equal to the permutation. The subsegment from the 33-rd to the 55-th positions is 3,1,23,1,2, there is only one subsequence of length 33 (3,1,23,1,2), but it is not a cyclic shift of the permutation.
In the second example the possible cyclic shifts are 1,21,2 and 2,12,1. The subsegment from the 11-st to the 22-nd positions is 1,11,1, its subsequences are not cyclic shifts of the permutation. The subsegment from the 22-nd to the 33-rd positions is 1,21,2, it coincides with the permutation. The subsegment from the 33 to the 44 positions is 2,22,2, its subsequences are not cyclic shifts of the permutation.
预处理每个字符的下一个字符是哪个. 最后一个字符的下一个是第一个字符.
从后往前遍历a数组, 记录当前字符的最近的下一个字符的位置(序列自动机)
下一个字符算作一步, 下两个字符算作两步, 倍增处理之后第n - 1个字符(组成长度为n的排列)的位置, 记作lim[i];
每次询问[L, R]时查询区间内是否存在一个位置的lim <= R;
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mn = 2e5 + 10;
const ll inf = 4e18;
int lim[4 * mn];
void update(int id, int l, int r, int num, int val)
{
if (l == r)
{
lim[id] = val;
return;
}
int mid = (l + r) >> 1;
if (num <= mid) update(2 * id, l, mid, num, val);
else update(2 * id + 1, mid + 1, r, num, val);
lim[id] = min(lim[2 * id], lim[2 * id + 1]);
}
int query(int id, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return lim[id];
int mid = (l + r) >> 1;
if (R <= mid)
return query(2 * id, l, mid, L, R);
else if (L >= mid + 1)
return query(2 * id + 1, mid + 1, r, L, R);
else
return min(query(2 * id, l, mid, L, mid), query(2 * id + 1, mid + 1, r, mid + 1, R));
}
int p[mn], a[mn], nx[mn], pos[mn], to[mn][30];
int main()
{
int n, m, q; scanf("%d %d %d", &n, &m, &q);
for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
for (int i = 1; i <= m; i++) scanf("%d", &a[i]);
// 每个字符的下一个
for (int i = 1; i <= n - 1; i++)
nx[p[i]] = p[i + 1];
nx[p[n]] = p[1];
for (int i = 1; i <= n; i++)
pos[i] = m + 1;
for (int i = 1; i <= m + 1; i++)
for (int j = 0; j <= 20; j++)
to[i][j] = m + 1;
for (int i = m; i >= 1; i--) // 序列自动机
{
to[i][0] = pos[nx[a[i]]];
pos[a[i]] = i;
}
for (int j = 1; j <= 20; j++) // 倍增
for (int i = 1; i <= m; i++)
to[i][j] = to[to[i][j - 1]][j - 1];
for (int i = 0; i < 4 * m; i++)
lim[i] = m + 1;
for (int i = 1; i <= m; i++)
{
int ti = i, step = n - 1;
for (int j = 20; j >= 0; j--)
{
if (to[ti][j] <= m && step - (1 << j) >= 0)
ti = to[ti][j], step -= (1 << j);
}
update(1, 1, m, i, step == 0 ? ti : m + 1);
}
while (q--)
{
int l, r; scanf("%d %d", &l, &r);
int ans = query(1, 1, m, l, r);
printf("%d", ans <= r ? 1 : 0);
}
return 0;
}