2020牛客多校第六场 K题 K-Bag(思维题)
链接:https://ac.nowcoder.com/acm/contest/5671/K
题目描述
A sequence is called kkk-bag, if and only if it is put in order by some (maybe one) permutations of 111 to kkk. For example, 1,2,3,2,1,3,3,2,11,2,3,2,1,3,3,2,11,2,3,2,1,3,3,2,1 is a valid 333-bag sequence.
Roundgod is not satisfied with kkk-bag, so she put forward part-kkk-bag, which is a contiguous subsequence of kkk-bag.
Wcy wants to know if the sequence of length nnn is a part-kkk-bag sequence.
Roundgod is not satisfied with kkk-bag, so she put forward part-kkk-bag, which is a contiguous subsequence of kkk-bag.
Wcy wants to know if the sequence of length nnn is a part-kkk-bag sequence.
输入描述:
The first line contains one integer T (1≤T≤20)T\ (1\le T\le 20)T (1≤T≤20), denoting the number of test cases. Then TTT test cases follow.
The first line of each test case contains two integers n,k (1≤n≤5⋅105,1≤k≤109)n,k\ (1\le n \le 5 \cdot 10^5,1\le k \le 10^9)n,k (1≤n≤5⋅105,1≤k≤109).
The second line of each test case contains nnn integers indicate the sequence.
It is guaranteed that ∑n≤2⋅106\sum n \le 2\cdot 10^6∑n≤2⋅106, the values of the sequence are between 111 and 10910^9109.
输出描述:
One line of each test case, if the sequence is a part-kkk-bag sequence, print "YES", otherwise print "NO".
示例1
输出
复制YES
题解:考虑寻找开始循环的起点,可以发现从起点后,每次必然是隔开K个的。可以尝试枚举起点,K>>N,先离散化。Len【】是以i为起点长度为len【i】的一段序列是没有重复元素的。
枚举起点判定,分两种情况后面长度还有K个及以上则每次需要要往后跳K个,即len【pos】=k才行,或者直接到末尾了pos+len【pos】-1=n。
#include <bits/stdc++.h> #define IO_read ios::sync_with_stdio(false);cin.tie(0) #define fre freopen("in.txt", "r", stdin) #define _for(i,a,b) for(int i=a; i< b; i++) #define _rep(i,a,b) for(int i=a; i<=b; i++) #define inf 0x3f3f3f3f #define lowbit(a) ((a)&-(a)) using namespace std; typedef long long ll; template <class T> void read(T &x) { char c; bool op=0; while(c=getchar(), c<'0'||c>'9') if(c=='-') op=1; x=c-'0'; while(c=getchar(), c>='0'&&c<='9') x=x*10+c-'0'; if(op) x=-x; } template <class T> void write(T x) { if(x<0) putchar('-'), x=-x; if(x>=10) write(x/10); putchar('0'+x%10); } const int maxn=1e6+5; int T, n, k; int a[maxn], b[maxn]; int pre[maxn], len[maxn]; int check() { int ok=0; for(int st=1; st<=min(k, len[1]+1); st++) { for(int p=st; p<=n; p+=k) { if(p+len[p]-1==n){ok=1; break;} else if(len[p]^k) break; } if(ok) break; } return ok? true:false; } int main() { read(T); while(T--) { read(n), read(k); _rep(i, 1, n) read(a[i]), b[i]=a[i]; sort(b+1, b+1+n); int cnt=unique(b+1, b+1+n)-(b+1); _rep(i, 1, n) a[i]=lower_bound(b+1, b+1+cnt, a[i])-(b+1)+1; int p=1; for(int i=1; i<=n; i++) { while(p<=n && !pre[a[p]]) pre[a[p]]++, p++; pre[a[i]]--, len[i]=p-i; } printf(check()? "YES\n":"NO\n"); } return 0; }