Bloqueo de algoritmos (mejor fuerza bruta)

Cuadra

El algoritmo de bloque consiste en dividir una secuencia en varios bloques y operar por separado para resolver el problema. En general, es "todo el bloque está empaquetado y mantenido, y los fragmentos se enumeran uno por uno".

Operación básica

//block每一块大小   sz 分块数目   pos[i] 第i个数对应的是第几个块
//st[j]第j个块开始的位置 ed[j]第j个块结束的位置	

        block=sqrt(n);   
	sz=n/block;
	if(n%block) sz++;
	for(int i=1;i<=sz;++i) {
		st[i]=(i-1)*block+1;
		ed[i]=i*block;
	}
	ed[sz]=n;
	for(int i=1;i<=n;i++) {
		pos[i]=(i-1)/block+1;
	}

Tome la pregunta de ejemplo P3372 para explicar la aplicación del bloque

Pregunta: Se pueden realizar dos operaciones en una secuencia: 1: sumar k a un cierto intervalo; 2: encontrar la suma de un cierto intervalo.

Solución de bloque:

(1) Defina la matriz a []: almacena los datos originales. Array sum []: representa la matriz de cada bloque add []: representa la suma de cada bloque

(2) Para la modificación del intervalo [L, R]: p = pos [L], q = pos [R]. Si q = p, es decir, el intervalo de modificación está en un bloque, entonces atraviese directamente la matriz de modificación a [] y la suma de pares [p] + = d * (R-L + 1). Si p! = Q, modifique el agregado directamente en el bloque que está completamente contenido en el intervalo de modificación. Modifique directamente sum y a [] para bloques que no están completamente contenidos en el intervalo.

(3) Para sumar el intervalo [L, R], p = pos [L], q = pos [R]. Si p = q significa que el intervalo de suma está en un bloque, atraviesa directamente el intervalo para la suma res = a [L] + ... a [R],

Suma el valor de add [p], es decir, res + = add [p] * (R-L + 1); por el contrario, suma el recorrido rápido completamente contenido en el intervalo, y luego uno a uno según el incompleto inclusión Traverse para resolver.

void modify(int d,int L,int R) {
    int p = pos[L], q = pos[R];
    if(p==q) {                      
       for(int i=L;i<=R;i++) a[i]+=d;
       sum[p]+=d*(R-L+1);
    } else {                        
       for(int i=p+1;i<=q-1;i++) add[i]+=d; 
       for(int i=L;i<=ed[p];i++) a[i]+=d;   
       sum[p]+=d*(ed[p]-L+1);
       for( int i=st[q];i<=R;i++) a[i]+=d;   
       sum[q]+=d*(R-st[q]+1);
    }
 }
ll query(int L,int R) {
    int p = pos[L], q = pos[R];
    ll res=0;
    if(p==q){                    
       for(int i=L;i<=R;i++) res+=a[i];
       res+=add[p]*(R-L+1);
    }
    else{
       for(int i=p+1;i<=q-1;i++)  res+=sum[i]+add[i]*(ed[i]-st[i]+1);//整块
       //部分块
       for(int i=L;i<=ed[p];i++)  res+=a[i];   
       res+=add[p]*(ed[p]-L+1);
       for(int i=st[q];i<=R;i++)  res+=a[i]; 
       res+=add[q]*(R-st[q]+1);
    }
    return res;
 }

Supongo que te gusta

Origin blog.csdn.net/qq_44132777/article/details/108818030
Recomendado
Clasificación