题目链接:
https://codeforces.com/contest/1143/problem/E
题目大意
给定一个排列
p
p
p,给定一个数组
b
b
b
每个询问给出
l
,
r
l,r
l,r问在
[
l
,
r
]
[l,r]
[l,r]中是否存在
p
p
p的循环排列
题解思路
需要预处理每个点作为右端点对应的左端点,然后和给定的区间长度作比较
直接处理的话是
O
(
n
∗
m
)
O(n*m)
O(n∗m)的复杂度
这个地方用到了一个比较nb的
倍
增
倍增
倍增操作
简单地说就是不一步步找,每次跳
2
i
2^i
2i步
详情见代码注释
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
#define int ll
#define debug cout<<"fuck"<<endl;
#define pb push_back
const int mod=(int)1e9+7;
const int maxn=(int)2e5+5;
ll quick_pow_mod(ll a,ll b,ll c)
{
ll res=1;while(b){if(b&1){res=(res*a)%c;}a=(a*a)%c;b=b>>1;}return res;
}
int n,m,k,t;
int f[maxn][25],pre[maxn],b[maxn],a[maxn],las[maxn],res[maxn];
signed main()
{
//cout<<pow(2,20)<<endl;
int T;
IOS
cin>>n>>m>>T;
for(int i=1;i<=n;i++)
{
cin>>a[i];//排列
}
for(int i=1;i<=n;i++)
{
if(i==1)
{
pre[a[1]]=a[n];
}
else
{
pre[a[i]]=a[i-1];
}
}
for(int i=1;i<=m;i++)
{
cin>>b[i];//数组
f[i][0]=las[pre[b[i]]];
for(int j=1;j<=20;j++)
{
//倍增操作,f[i][j]表示位置i往前2^j个元素的位置
f[i][j]=f[f[i][j-1]][j-1];//i往前2^(j-1)再往前2^(j-1)
}
las[b[i]]=i;//每次更新las
int pos=i;
for(int j=0;j<=20;j++)
{
if((1<<j)&(n-1))
{
pos=f[pos][j];
}
}
res[i]=max(res[i-1],pos);//枚举右端点不一定以右端点作为结束点
}
/*for(int i=1;i<=m;i++)
{
cout<<res[i]<<' ';
}cout<<endl;*/
int x,y;
while(T--)
{
cin>>x>>y;
if(res[y]>=x)cout<<1;
else cout<<0;
}
return 0;
}