CF1142B Lynyrd Skynyrd

Link
有两种做法:
第一种是(O(nlog n))的。
我们预处理两个数组:
(pre_i)表示(p)(i)前面的那个数是(pre_i)
(lst_i)表示(a)(a_i)前一个(pre_{a_i})的位置。(代码中是(f_0)
那么每个数往前跳几次(lst),也就会对应排列(p)中的一段连续子串。
然后处理往前跳(lst)的倍增数组。
我们知道,(p)是一个循环排列,所以对于每个数,以这个数结束的最短的是(p)的循环移位的(a)的子序列,就是从这个数往前跳(n-1)(lst)得到的子序列。
所以我们处理出每个点往前跳(n-1)(lst)得到的位置(edp)
对于一次询问(l,r),如果(l,r)中存在子序列为(p)的循环移位,那么就会满足(exist iin[l,r],edp_iin[l,r])
所以我们用(st)表维护区间最小值即可。

#include<bits/stdc++.h>
using namespace std;
const int N=200007;
int p[N],a[N],f[21][N],pre[N],lst[N],Log[N],st[21][N];
int max(int a,int b){return a>b? a:b;}
int read(){int x;scanf("%d",&x);return x;}
int get(int l,int r){int k=Log[r-l+1];return max(st[k][l],st[k][r-(1<<k)+1]);}
int main()
{
	int n=read(),m=read(),q=read(),i,j,l,r;
	for(i=1;i<=n;++i) p[i]=read();
	p[0]=p[n];
	for(i=1;i<=n;++i) pre[p[i]]=p[i-1];
	for(i=1;i<=m;++i) a[i]=read();
	for(i=1;i<=m;++i) f[0][i]=lst[pre[a[i]]],lst[a[i]]=i;
	for(i=2;i<=n||i<=m;++i) Log[i]=Log[i>>1]+1;
	for(i=1;i<=Log[n];++i) for(j=1;j<=m;++j) f[i][j]=f[i-1][f[i-1][j]];
	for(i=1;i<=m;++i) for(st[j=0][i]=i;j<=Log[n-1];++j) if((n-1)&(1<<j)) st[0][i]=f[j][st[0][i]];
	for(i=1;i<=Log[m];++i) for(j=1;j+(1<<i)-1<=m;++j) st[i][j]=max(st[i-1][j],st[i-1][j+(1<<i-1)]);
	while(q--) l=read(),r=read(),putchar(get(l,r)>=l? '1':'0');
}

第二种是(O(n))的。
我们处理两个数组:
(ppre_i)表示(p)(i)前面的那个数是(ppre_i)
(apre_i)表示(a)中前一个(a_i)的位置。
然后从前往后扫(a)数组,把(a_i)前面所有未连边的(ppre_{a_i})的位置向(i)连边,并且打上标记,下次不再连边。
那么我们知道每个点最多只有一个入边。没有入边的,我们新建一个(0)到这个点的边。
总的,我们会建出一棵树。
(a)数组中(a_i)向前跳一次(lst)(上面那个做法的跳)也就是跳一次父亲。
所以上面做法的跳(n-1)次就变成了(n-1)级祖先。
考虑dfs的过程,dfs到某个点经过的点(也就是dfs的栈)存的都是根到当前节点的路径。
所以每个节点dfs到时(进栈)把当前深度的节点((b)数组)记为自己,因此(n-1)级祖先就是(b[dep[u]-(n-1)])

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=200007;
int n,m,q,p[N],a[N],apre[N],lst[N],ppre[N],fa[N],dep[N],w[N],b[N];
vector<int>G[N];
int max(int a,int b){return a>b? a:b;}
int min(int a,int b){return a<b? a:b;}
int read(){int x;scanf("%d",&x);return x;}
void dfs(int u)
{
    int i,v;
    b[dep[u]]=u,w[u]=dep[u]>=n? b[dep[u]-(n-1)]:m+1;
    for(i=G[u].size()-1;~i;--i) v=G[u][i],dep[v]=dep[u]+1,dfs(v);
}
int main()
{
    n=read(),m=read(),q=read();int i,j;
    for(i=1;i<=n;++i) p[i]=read();
    p[0]=p[n];
    for(i=1;i<=n;++i) ppre[p[i]]=p[i-1];
    for(i=1;i<=m;++i)
    {
	a[i]=read(),apre[i]=lst[a[i]],lst[a[i]]=i;
	for(j=lst[ppre[a[i]]];j&&!fa[j];j=apre[j]) fa[j]=i;
    }
    for(i=1;i<=m;++i) fa[i]? G[fa[i]].pb(i):G[0].pb(i);
    dfs(0);
    for(i=m-1;i;--i) w[i]=min(w[i+1],w[i]);
    while(q--) i=read(),j=read(),putchar(48+(w[i]<=j));
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/11527122.html