传送门
只要维护一个切割点数组cut[i],表明从1~i的切割是有效的,且可与后半部分拼接。维护好cut后只要从后往前再扫一遍即可。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define MAXN 2005005
int n,k;
int a[MAXN];
int cut[MAXN];
unordered_map<int,int>mp;
int main()
{
int t;
cin>>t;
while(t--)
{
mp.clear();
scanf("%d%d",&n,&k);
int flag=0;
for(int i=1;i<=n;i++) {
cut[i]=0;
scanf("%d", a + i);
if(a[i]>k)flag=1;
}
if(flag){
cout<<"NO"<<endl;continue;}
int cnt=0;
cut[0]=1;
for(int i=1;i<=n;i++)
{
if(i>k){
mp[a[i-k]]--;
if(mp[a[i-k]]==0)cnt--;
}
mp[a[i]]++;
if(mp[a[i]]==1)cnt++;
if(cnt==k||cnt==i)cut[i]=i>=k?cut[i-k]:1;
}
cnt=0;mp.clear();
for(int i=n;i>=max(0,n-k);i--)
{
if(cnt==n-i&&cut[i])flag=1;
mp[a[i]]++;
if(mp[a[i]]==1)cnt++;
}
printf(flag?"YES\n":"NO\n");
}
}