牛客多校第6场K-K-bag

题意

K-bag是一个正整数序列,由若干个 1 1 1~ k k k的排列排成,其连续子序列被称为部分K-bag。
给出一个序列和正整数 k k k,判断该序列是不是部分K-bag。
( n ≤ 5 e 5 , k ≤ 1 e 9 ) (n\leq5e5,k\leq1e9) (n5e5,k1e9)

题解

题目给的 k k k很大,所以在 k k k上做文章有点难。
考虑直接扫一遍,用 O ( n ) O(n) O(n)做法或 O ( n l o g n ) O(nlogn) O(nlogn)做法。
一开始若有数字大于 k k k直接输出。
设数组 f [ i ] f[i] f[i],记录序列 1 1 1~ i i i是否可以为一个部分K-bag。
为维护 f [ i ] f[i] f[i],我们需要定义一个 t o t tot tot,记录 ( i − k + 1 ) (i-k+1) (ik+1)~ i i i这一段上,一共有几种不同数字。
那么我们有需要一个哈希表来统计这一段上数字的出现数组,实现方式可以用 u n o r d e r e d _ m a p unordered\_map unordered_map(因为 m a p map map会超时)或离散化使数字均小于 5 e 5 5e5 5e5然后直接用数组哈希。
若序列用 a [ i ] a[i] a[i]表示,
那么就有 i f ( i > n & & ! − − h a s h [ a [ i − k ] )   t o t − − ; if(i>n\&\&!--hash[a[i-k])\ tot--; if(i>n&&!hash[a[ik]) tot; i f ( h a s h [ a [ i ] ] = = 0 )   t o t + + ; if(hash[a[i]]==0)\ tot++; if(hash[a[i]]==0) tot++;
i < k ii<k时, f [ i ] = t o t = = i ? 1 : 0 ; f[i]=tot==i?1:0; f[i]=tot==i?1:0;
i > = k i>=k i>=k时, f [ i ] = t o t = = k ? f [ i − k ] : 0 ; ( f [ 0 ] = 1 ) f[i]=tot==k?f[i-k]:0;(f[0]=1) f[i]=tot==k?f[ik]:0;(f[0]=1)
最后从后往前查找最后 k k k个数字,看最后这一段能否符合以及此处 f f f值是否为 1 1 1。找到一个符合条件的即为 Y E S YES YES,否则为 N O NO NO

#include
int a[500010],f[500010],id[500010],tong[500010];
int main(){
    int T; scanf("%d",&T);
    while(T--){
        memset(tong,0,sizeof(tong)); memset(f,0,sizeof(f)); f[0]=1;
        int n,k,tag=0,tot=0,ans=0; scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++) scanf("%d",a+i),tag=a[i]>k?1:0,id[i]=a[i];
        std::sort(id+1,id+n+1);
        int len=std::unique(id+1,id+n+1)-id-1;
        for(int i=1;i<=n;i++) a[i]=std::lower_bound(id+1,id+len+1,a[i])-id;
        if(tag) {printf("NO\n");continue;}
        for(int i=1;i<=n;i++){
            if(i>k) if(!--tong[a[i-k]]) tot--;
            if(!tong[a[i]]) tot++;
            tong[a[i]]++;
            if(i>=k&&tot==k) f[i]=f[i-k];
            if(i<k&&tot==i) f[i]=1;
        }
        tot=0; memset(tong,0,sizeof(tong));
        for(int i=n;i>=std::max(n-k,0);i--){
            if(f[i]&&tot==n-i) {ans=1;break;}
            if(!tong[a[i]]) tot++;
            tong[a[i]]++;
        }
        if(ans) printf("YES\n"); else printf("NO\n");
    }
}

你可能感兴趣的:(牛客多校第6场K-K-bag)