[序列自动机+倍增] 查询是否存在一个给出的全排列的循环右移是给定区间的子序列 CF1143E

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;
}

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值