题目链接
思路:
首先判断每一位置之后有多少个不重复的数字,然后再枚举所有可能的第一个断点的位置,遍历判断从这个断点开始之后的每一个断点是否可以成为一个排列,因为k=1e9,所以我们要用到离散化。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int N=1e5+7;
const double eps=1e-8;
const int mod=1e9+7;
const int inf=0x7fffffff;
const double pi=3.1415926;
int a[510000],b[510000],len[510000],pre[510000];
signed main()
{
IOS;
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
int ok=1;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i]=a[i];
if(a[i]>k||a[i]<0)
{
ok=0;
}
}
if(!ok)
{
cout<<"NO"<<endl;
continue;
}
sort(b+1,b+n+1);
int cnt=unique(b+1,b+n+1)-b-1;//去重
for(int i=1;i<=n;i++)//离散化
{
a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
}
int p=1;
for(int i=1;i<=n;i++)//判断从i开始之后连续且不重复的数字有多少位
{
while(!pre[a[p]]&&p<=n)
{
pre[a[p]]++;
p++;
}
pre[a[i]]--;
len[i]=p-i;
}
int sc=0;
for(int st=1;st<=min(k,len[1]+1);st++)
{
bool flag=true;
for(int i=st;i<=n;i+=k)
{
if(i+len[i]>=n+1)
{
continue;
}
else if(len[i]!=k)
{
flag=false;
break;
}
}
if(flag==true)
{
sc=1;
break;
}
}
cout<<(sc?"YES":"NO")<<endl;
}
return 0;
}