2020牛客多校第六場K題K-Bag(離散化)
阿新 • • 發佈:2020-08-02
https://ac.nowcoder.com/acm/contest/5671/K
題意:定義一個概念kbag:1-k的排列。3bag表示為{1,2,3,2,1,3,3,2,1}長度不限,輸入n,k,n長的序列,判斷是不是part-kbag。
題解:
當ai<1或ai>k,不為partK−bag
由於可能有k>n,故此時需要離散化或者用map存,都是O(nlogn)
一個part-k−bag的組成:一個或零個不完整的k排列+K−bag+一個或零個不完整的k排列。
考慮列舉起點,最多k個起點。首先找到每個元素可以到達的往後的最遠位置,用len[i]表示位置在 i的元素可到達的最遠位置,如果為k則說明可以組成一個完整的k排列,
否則就判斷是否有i+len[i]>=n+1,如果有則說明該起點得到了一個合法的partK−bag,否則該起點得不到。
那麼就可以列舉最多k個起點,說明從i到n可以組成一個不完整的k排列。
該種列舉方法考慮的是從K−bag+一個或零個不完整的k排列,開頭的不完整的k排列自動判斷正確。
#include <bits/stdc++.h> using namespace std; const int maxn=5e5+7; int a[maxn],b[maxn],pre[maxn],len[maxn];int main(){ int t,n,k; scanf("%d",&t); while(t--){ memset(pre,0,sizeof(pre)); scanf("%d%d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; } sort(b+1,b+n+1); int cnt=unique(b+1,b+n+1)-(b+1); for(int i=1;i<=n;i++){ a[i]=lower_bound(b+1,b+cnt+1,a[i])-b; } int p=1,ans=0; for(int i=1;i<=n;i++){ while( !pre[ a[p]] && p<=n) { pre[a[p]]++; p++; } pre[a[i]]--; len[i]=p-i; } for(int s=1;s<=min(k,len[1]+1);s++){ int f=1; for(int i=s;i<=n;i+=k){ if( i+len[i] >=n+1) continue; else if( len[i]^k){ f=0;break; } } if(f) { ans=1;break; } } if(ans) puts("YES"); else puts("NO"); } return 0; }