K-Bag(DP)
思路:
d
p
+
u
n
o
r
d
e
r
e
d
_
m
a
p
dp+unordered\_map
dp+unordered_map。
考虑:令
d
p
[
i
]
dp[i]
dp[i]点
i
i
i能否别切割,即前
i
i
i个数能否成为一个
p
a
r
t
−
k
part-k
part−k序列。
这一步可以用 u n o r d e r e d _ m a p unordered\_map unordered_map记数统计,需要注意的是当 i < k i<k i<k时需要将前 i i i个数是否为一个部分序列考虑进去,其他情况只用考虑 k k k个数。
然后从后往前扫最多 k k k个数,判断 d p [ i ] dp[i] dp[i]和 c n t = = n − i cnt==n-i cnt==n−i同时成立,若存在则成立。
时间复杂度: O ( n ) O(n) O(n)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
int t,n,k,a[N],cnt,ok;
bool dp[N];
unordered_map<int,int>mp;//用map会T.
bool solve(){
mp.clear(),cnt=0;
memset(dp,false,sizeof dp);
dp[0]=true;
for(int i=1;i<=n;i++){
if(i>k) if(!--mp[a[i-k]]) cnt--;
if(!mp[a[i]]++) cnt++;
if(cnt==k||cnt==i) dp[i]=i-k>=0?dp[i-k]:1;
}
mp.clear(),cnt=0;
for(int i=n;i>=max(n-k,0);i--){
if(dp[i]&&cnt==n-i) return true;
if(!mp[a[i]]++) cnt++;
}
return false;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
ok=1;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]>k||a[i]<1) ok=0;
}
if(!ok){
puts("NO");continue;
}
puts(solve()?"YES":"NO");
}
return 0;
}