2020 Niuke Summer Multi-School Training Camp (Sixth Session) K-Bag (Supplementary Question)

https://ac.nowcoder.com/acm/contest/5671/E

Solution: If the sequence is a continuous substring of k-bag, one of the following three conditions is satisfied:

1. A partial k-bag prefix + several complete k-bags + a partial k-bag suffix

2. A prefix of a partial k-bag + a suffix of a partial k-bag

3. A partial k-bag

Judgment part k-bag: only need to judge whether the number of different numbers in the interval is equal to the length of the interval.

Here cnt1[i] indicates how many different numbers are in the interval from 1 to i, and cnt2[i] indicates how many different numbers are in the interval from n to i

Determine the complete k-bag: continuous sequence [l,r], maintain sum and xor, sum = l + (l + 1) + ... + (r-1) + r, xor = l ^ (l + 1 ) ^ ... ^ (r-1) ^ r, forming a binary pair <sum, xor >, this binary pair and [l, r] are in a one-to-one correspondence. (Here to prevent conflicts, for each Multiply the value by 131, and then sum, XOR)

For n>k, it can only be conditions 1 and 2. We enumerate [1,k] as the starting point of the first complete k-bag, and then judge whether each interval of length k is satisfied, according to the preprocessing prefix and XOR and

For k>=n, it can only be conditions 2 and 3. Then we enumerate the breakpoints to judge the front part and the back part.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
ll a[maxn],n,k;
ll sum[maxn],Xor[maxn],S,X;
unordered_map<ll,ll> mp;
int cnt1[maxn],cnt2[maxn];

bool check(int st) {
	for(int i=st;i<=n;i+=k) {
		int l=i,r=i+k-1;
		if(r<=n) {
			if(sum[r]-sum[l-1]!=S||(Xor[r]^Xor[l-1])!=X)
				return false;
		} else return cnt2[l]==n-l+1;
	}
	return true;
} 
void init() {
	mp.clear();
	cnt1[0]=0;
	for(int i=1;i<=n;i++) {
		cnt1[i]=cnt1[i-1];
		if(!mp[a[i]]) cnt1[i]++;
		mp[a[i]]++;
	}
	mp.clear();
	cnt2[n+1]=0;
	for(int i=n;i>=1;--i) {
		cnt2[i]=cnt2[i+1];
		if(!mp[a[i]]) cnt2[i]++;
		mp[a[i]]++;
	}
}
bool solve() {
	if(k<n) {
		S=X=0;
		for(int i=1;i<=k;i++) S+=(i*131),X^=(i*131);
		for(int i=1;i<=k;i++) {
			if(cnt1[i-1]!=i-1) {
				break;
			}
			if(check(i)) return true;
		}
	} else {
		for(int i=2;i<=n;i++) {
			if(cnt1[i-1]==i-1&&cnt2[i]==n-i+1) return true;
		}
	}
	return false;	
}
signed main() {
	int test; scanf("%d",&test);
	while(test--) {
		scanf("%lld%lld",&n,&k);
		int flag=0;
		for(int i=1;i<=n;i++) {
			scanf("%lld",a+i);
			if(a[i]<1||a[i]>k) flag=1;
			a[i]=a[i]*131;
			sum[i]=sum[i-1]+a[i];
			Xor[i]=Xor[i-1]^a[i];
			//每一个数乘以131然后哈希,防止冲突 
		}
		if(flag) {
			puts("NO");
			continue;
		}
		init();
		if(solve()) puts("YES");
		else puts("NO");
	}
	
	
	
}

 

Guess you like

Origin blog.csdn.net/qq_44132777/article/details/107708010