题目
题目链接:https://ac.nowcoder.com/acm/contest/5671/K
思路
先枚举起点 注意起点要0~k-1
把每个下标对应的起点标记起来
滑动窗口每次取K个判定
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define ll long long
int a[5000100],cnt[5000100];
bool vis[5000100];
unordered_map<ll,ll> mp,mp2;
signed main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++) cin>>a[i],cnt[i]=0,vis[i]=0;
mp.clear();
vis[0]=0,cnt[0]=0;
if(k>=n){
mp2.clear();
bool flag=0,flag1=0;
for(int i=1;i<=n;i++){
if(a[i]>k) flag1=1;
if(mp2[a[i]]&&mp[a[i]]>=1) flag1=1;
mp[a[i]]++;
if(mp[a[i]]==2) flag=1;
if(flag) mp2[a[i]]=1;
}
if(flag1) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
else{
int num=0;
for(int i=0;i<=k-1;i++){
//vis[i]=0;
int m=i+k;
while(m<=n){
cnt[m]=i;
m+=k;
}
}
bool flag1=0;
// for(int i=1;i<=n;i++) cout<<cnt[i]<<endl;
for(int i=1;i<=n;i++){
if(i<=k-1){
mp[a[i]]++;
if(mp[a[i]]==2) num++;
if(num) vis[i]=1;
if(a[i]>k) flag1=1;
}
else{
mp[a[i]]++;
if(mp[a[i]]==2) num++;
if(i-k>0){if(mp[a[i-k]]==2) num--;mp[a[i-k]]--;}
// cout<<mp[a[i]]<<" "<<i<<endl;
// cout<<cnt[i]<<" "<<vis[cnt[i]]<<endl;
if(num) vis[cnt[i]]=1;
if(a[i]>k) flag1=1;
// cout<<num<<" "<<a[i]<<" "<<vis[cnt[i]]<<endl;
}
}
for(int i=n-k+1;i<=n;i++){
// cout<<a[i]<<" "<<i<<" "<<mp[a[i]]<<endl;
if(mp[a[i]]){
if(mp[a[i]]==2) num--;
mp[a[i]]--;}
if(num){
if(i<=k-1) vis[i]=1;
else vis[cnt[i]]=1;}
//cout<<a[i]<<" "<<i<<" "<<mp.size()<<endl;
// for(auto i:mp) cout<<i.first<<" "<<i.second<<endl;
}
bool flag=0;
for(int i=0;i<=k-1;i++) if(!vis[i]) flag=1;
if(!vis[cnt[k]]) flag=1;
if(flag&&!flag1) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
return 0;
}