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;
}