K-Bag(DP)

K-Bag(DP)

思路: d p + u n o r d e r e d _ m a p dp+unordered\_map
考虑:令 d p [ i ] dp[i] i i 能否别切割,即前 i i 个数能否成为一个 p a r t k part-k 序列。

这一步可以用 u n o r d e r e d _ m a p unordered\_map 记数统计,需要注意的是当 i < k i<k 时需要将前 i i 个数是否为一个部分序列考虑进去,其他情况只用考虑 k k 个数。

然后从后往前扫最多 k k 个数,判断 d p [ i ] dp[i] c n t = = n i cnt==n-i 同时成立,若存在则成立。

时间复杂度: 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;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107622323