1. 程式人生 > 實用技巧 >2020牛客多校第六場 K題 K-Bag(思維題)

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 of111to 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 valid333-bag sequence.
Roundgod is not satisfied with kkk-bag, so she put forward part-kkk-bag, whichis a contiguous subsequence of kkk-bag.
Wcy wants to know if the sequence of lengthnnn is a part-kkk-bag sequence.

輸入描述:

The first line contains one integer T(1≤T≤20)T\ (1\le T\le 20)T(1T20), denoting the number of test cases. ThenTTTtest 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(1n5105,1k109).
The second line of each test case containsnnn integers indicate the sequence. It is guaranteed that∑n≤2⋅106\sum n \le 2\cdot 10^6n2106, the values of the sequence are between 111and 10910^9109.

輸出描述:

One line of each test case, if the sequence is a part-kkk-bag sequence, print "YES", otherwise print "NO".
示例1

輸入

複製
1
8 3
2 3 2 1 3 3 2 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;
}