2020 牛客多校第六场 K bag(滑动窗口维护k排列)

题目

题目链接

思路

考虑用滑动窗口来维护多个合法且连续的k序列
维护一个滑动窗口,标记左右端点为L R
每次延伸右端点,要进行判断。
判断新加入的元素它的个数是否等于当前所在的段数(第几个k序列),如果大于,则更新修改左端点直到符合条件。不断维护,则可求解。
该滑动窗口最终维护获得的是 多个合法k bag + 一个部分 k bag的串,然后对L前面一段字符串进行判断即可确定整个串是否为合法的。

代码

#include 
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 10;
const ll mod = 1e9 + 7;
int n;
int a[maxn];
int main(){
	int t;
	scanf("%d", &t);
	while(t--){
        int n, k; scanf("%d %d", &n, &k);
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
        }
        int i = 1, j = 1;//L R
        unordered_map <int, int> mp;
        bool flag = true;
        while(j <= n){
            if(a[j] < 1 || a[j] > k){
                flag = false;
                break;
            }
            mp[a[j++]]++;
            while((j - 1 - i + 1 + k - 1) / k != mp[a[j - 1]]){//更新左侧直到符合
                mp[a[i++]]--;
            }//保证了滑动窗口中的序列一定符合题意要求
        }
        unordered_set <int> sett;
        for(int x = 1; x < i; x++){
            if(sett.count(a[x])){
                flag = false;
                break;
            }
            sett.insert(a[x]);
        }
        if(flag){
            printf("YES\n");
        }else{
            printf("NO\n");
        }
	}
	return 0;
}

你可能感兴趣的:(2020 牛客多校第六场 K bag(滑动窗口维护k排列))