这题好像是个论文题??有个论文证明了这题做法的复杂度但是我太懒了没去看….
一开始我以为这题是反着构造使F(x,y)为true的x,y序列,然后得到什么结论什么的
想了一会没得到什么有用的东西就弃疗了
(连续相同的元素可以合并好像对搜索还是挺有用的一个性质
问了Claris这题居然是搜索qwq
注意到元素集合|S|<=100,因为F(x,y)的柿子每次去掉一种元素,所以不会超过100层
然后这个p(x),x的最长前缀使得W(p(x))!=W(x),可以理解为去掉了最右端的元素
s(x)同理理解为去掉了最左端的元素
然后我们yy一下这个搜索过程…
F(x,y)分到下一层,去掉最右端的元素,去掉最左端的元素
不断这样分….左右分出来的交集肯定越来越小
那么去找p(x),s(x)的时候,在用一层里,同一个位置被遍历的次数不会太多qwq(Claris说是常数次?qwq我不懂)
于是你可以把同一层的看作一个O(n)
100层就是100n了
记忆化一下,用v[dep][l1]存储搜过的状态,dep代表层数,层数,l1确定了,r1,l2,r2也是确定的
然后就可以了qwq
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
inline void read(int &x)
{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
const int maxn = 110000;
const int maxx = 110;
int n,m,al;
int a[maxn],b[maxn];
int vi[maxx],ti;
bool v[maxx][maxn];
bool solve(int d,int l1,int r1,int l2,int r2)
{
if(v[d][l1]) return true;
if(l1==r1) return v[d][l1]=a[l1]==b[l2]?true:false;
int np1,np2,now;
now=0; ++ti;
for(int i=l1;i<=r1;i++)
{
if(vi[a[i]]!=ti) vi[a[i]]=ti,now++;
if(now==al-d+1) { np1=i-1; break; }
}
now=0; ++ti;
for(int i=l2;i<=r2;i++)
{
if(vi[b[i]]!=ti) vi[b[i]]=ti,now++;
if(now==al-d+1) { np2=i-1; break; }
}
if(!solve(d+1,l1,np1,l2,np2)) return false;
now=0; ++ti;
for(int i=r1;i>=l1;i--)
{
if(vi[a[i]]!=ti) vi[a[i]]=ti,now++;
if(now==al-d+1) { np1=i+1; break; }
}
now=0; ++ti;
for(int i=r2;i>=l2;i--)
{
if(vi[b[i]]!=ti) vi[b[i]]=ti,now++;
if(now==al-d+1) { np2=i+1; break; }
}
if(!solve(d+1,np1,r1,np2,r2)) return false;
return v[d][l1]=true;
}
int main()
{
int tcase; read(tcase);
while(tcase--)
{
ti=0; for(int i=1;i<maxx;i++) vi[i]=ti;
read(n); read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=m;i++) read(b[i]);
int nn=0;
for(int i=1;i<=n;i++) if(a[i]!=a[i-1])
a[++nn]=a[i];
n=nn;
int mm=0;
for(int i=1;i<=m;i++) if(b[i]!=b[i-1])
b[++mm]=b[i];
m=mm;
for(int i=1;i<=n;i++) vi[a[i]]=1;
bool flag=true; al=0;
for(int i=1;i<=m;i++)
{
if(!vi[b[i]]) { flag=false; break; }
else if(vi[b[i]]==1) vi[b[i]]=2,al++;
}
for(int i=1;i<maxx&&flag;i++) if(vi[i]==1) flag=false;
if(!flag) { puts("0");continue; }
ti=0; for(int i=0;i<maxx;i++) vi[i]=ti;
for(int i=1;i<maxx;i++) for(int j=1;j<=n;j++) v[i][j]=false;
puts(solve(1,1,n,1,m)?"1":"0");
}
return 0;
}