Sexto K-K-bag (pensando)

Título aquí

Significado de la pregunta: defina k-bag como una secuencia compuesta de varias secuencias de 1 a k, cada secuencia 1 ~ k solo puede contener k números, es decir, no se puede repetir, como 1 2 3 2 3 1 3 2 1 se llama uno 3 bolsas. Una subsecuencia continua de k-bag también se denomina parte k-bag. Ahora, dados n números yk, pregúntele si estos n números son una parte de k-bag.

Idea: Primero usamos una matriz len para determinar la longitud de la secuencia única comenzando desde la posición actual. Cuando se encuentra la posición actual de len [i] == k, significa que la parte media de la secuencia puede formar k secuencias no repetitivas, de modo que la longitud de k se incrementa cada vez, si la longitud de len siempre es igual a k, es factible .
Debido a que la secuencia dada está incompleta, además de la parte completa en el medio, puede haber algunas partes que deban agregarse antes y después para formar una secuencia k. Por lo tanto, necesitamos usar las partes sin círculo al frente como punto de partida para la enumeración, porque no Sabiendo que los primeros incompletos pueden formar una secuencia k completa, entonces enumere la posición desde el punto inicial hasta el punto donde la posición inicial se repite por primera vez. Ya que yendo más atrás, las anteriores no pueden formar una secuencia k, y cuando una Cuando la posición del punto más len es mayor que n, significa que no hay puntos repetidos después de este punto, y esta parte también se puede completar como una secuencia k.

Esta pregunta k <= 1e9, si usa una matriz para registrar el número actual de ocurrencias, no se mostrará, por lo que debe discretizar la matriz dada

Código:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN = 5e5+7;
int a[MAXN],b[MAXN],len[MAXN],pre[MAXN];
int n,k;

void lisan()
{
    
    
	for(int i = 1;i <= n;i ++){
    
    
		scanf("%d",&a[i]);
		b[i] = a[i];
	}
	sort(b+1,b+1+n);
	int cnt = unique(b+1,b+1+n)-b-1;
	for(int i = 1;i <= n;i ++){
    
    
		a[i] = lower_bound(b+1,b+1+cnt,a[i])-b;
	}
}

int main()
{
    
    
	int t;
	scanf("%d",&t);
	while(t--){
    
    
		scanf("%d%d",&n,&k);
		lisan();
		int pos = 1,flag = 0;
		for(int i = 1;i <= n;i ++){
    
    
			while(!pre[a[pos]] && pos <= n)
				++pre[a[pos]],pos++;//一直没有出现过 就是一直都没有重复就往后加就行了
			--pre[a[i]];//当了前位置 把这个位置的减掉后面的相同的才可以进来
			len[i] = pos - i;
		}
		int ed = min(k,len[1]+1);//来确定起点有几种可能性 要么与开头第一个重复,要么就是k 超过k也没有意义了
		for(int i = 1;i <= ed;i ++){
    
    
			int f = 1;
			for(int j = i;j <= n;j += k){
    
    
				if(j + len[j] > n) continue;
				else if(len[j] != k){
    
    
					f = 0;//这个起点不可行
					break;
				}
			}
			if(f == 1){
    
    //找到了一个可行的起点 就完成了
				flag = 1;
				break;
			}
		}
		if(flag) puts("YES");
		else puts("NO");
	}
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45672411/article/details/107663552
Recomendado
Clasificación