Conceptos básicos de bloques (simples y fáciles de entender)

Bloquear

El bloqueo se considera una violencia elegante, principalmente por la cuestión del intervalo.

Bloquear significa dividir un segmento en muchos bloques,

Usualmente usamos x = sqrt (n) para representar el tamaño de un bloque

num = ceil (n × \ veces× 1.0 / x) para indicar el número de bloques

El requisito principal para la fragmentación son 3 matrices,

pos [i] es para indicar el bloque donde se encuentra el i-ésimo número

l [i] representa el punto final izquierdo del i-ésimo bloque

r [i] representa el punto final derecho del i-ésimo bloque

Por ejemplo, la siguiente pregunta

Tenemos que crear otra matriz ans [i] para representar el número que agregamos al bloque i-ésimo.

Pero esto da lugar a una pregunta, si el bloque i-ésimo incluido en el intervalo agregado está incompleto, ¿podemos agregar c on ans [i],

La respuesta es no.

Para bloques incompletos, deberíamos resolverlos violentamente agregando c a la matriz a, es decir, la matriz original

Para el bloque completo, solo necesitamos agregar c a la matriz ans.

Entonces, el resultado final es que el tamaño del número i-ésimo es un [i] + ans [pos [i]]

Descripción del Título

Dada una secuencia de operaciones de longitud n y n, las operaciones implican la suma de intervalos y la búsqueda de un solo punto.

Formato de entrada

Ingrese un número en la primera línea. Ingrese n números en la segunda línea y el i- ésimo número es una [i] , separados por espacios.

Luego, ingrese n líneas de consulta e ingrese cuatro dígitos opt, l, r, c en cada línea separados por espacios,

Si opt = 0 significa sumar c a todos los números entre [l, r].

Si opt = 1 , significa pedir el valor de a [r]

Formato de salida

Para cada consulta, genere un número en una línea para indicar la respuesta.

Muestra

Entrada de muestra

4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0

Salida de muestra

2
5
#include<bits/stdc++.h>
using namespace std;
int l[2005],r[2005] ,pos[50005],a[50005],ans[50005];
void add(int ll,int rr,int v)
{
	int posl=pos[ll];
	int posr=pos[rr];
	if(posr-posl<=1)/*这个表示要加的区间在一个块内,即直接在原数组a上加*/
	{
		for(int i=ll;i<=rr;i++)
		{
			a[i]=a[i]+v;
		}
		
	}
	else
	{
		for(int i=ll;i<=r[posl];i++)/*前面的不完整的块*/
		a[i]=a[i]+v;
		for(int i=pos[ll]+1;i<pos[rr];i++)/*完整的块*/
		ans[i]+=v;
		for(int i=l[posr];i<=rr;i++)/*后面不完整的块*/
		a[i]=a[i]+v;
	}
	
}
void shuchu(int rr)
{
	if(ans[pos[rr]])
	printf("%d\n",a[rr]+ans[pos[rr]]);
	else
	printf("%d\n",a[rr]);
}
int main()
{
	int n;
	int opt ,ll,rr,cc;
	cin>>n;
	int x=sqrt(n);
	int num=ceil(n*1.0/x);
	for(int i=1;i<=num;i++)/*预处理l和r 数组*/
	{
		l[i]=(i-1)*x+1;
		r[i]=i*x;
	}
	r[num]=n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		pos[i]=(i-1)/x+1;	/*处理pos数组*/
	}
	for(int i=1;i<=n;i++)
	{
		cin>>opt>>ll>>rr>>cc;
		if(opt==0)
		{
			add(ll,rr,cc);
		}
		else
		{
			shuchu(rr);
		}
		
	}
	return 0;
}

Supongo que te gusta

Origin blog.csdn.net/hhuhgfhggy/article/details/108978595
Recomendado
Clasificación