HUD-3333 fuera de línea + matriz de árbol + intervalo diferentes valores e + ideas

Esta es la primera vez que hago este tipo de preguntas y no tengo este tipo de pensamiento. Resumamos.
HUD-3333 es una solución a la suma de elementos únicos en un intervalo específico. Dado que los datos de entrada son muy grandes y no se discretizarán, el mapa se utiliza para asignar diferentes valores.
 

Idea principal:

Ahora dadas N secuencias numéricas A1, A2, ..., AN y múltiples consultas (i, j) (1≤i≤j≤N). Para cada consulta (i, j), calculará la suma de diferentes valores en la subsecuencia Ai, Ai + 1, ..., Aj.


Entrada La
primera línea es un número entero T (1≤T≤10), que determina el número de casos de prueba a continuación.
Para cada caso, el formato de entrada es el siguiente:
* Línea 1: N (1≤N≤30.000).
* Línea 2: N enteros A1, A2, ..., AN (0≤Ai≤1,000,000,000).
* Línea 3: Q (1≤Q≤100,000), el número de consultas.
* Siguiente Q filas: cada fila contiene 2 enteros i, j, que representan una consulta (1≤i≤j≤N).

Salida
Para cada consulta, imprima la suma de los diferentes valores de la subsecuencia especificada en una línea.

Entrada de muestra
2
3
1 1 4
2
1 2
2 3
5
1 1 2 1 3
3
1 5
2 4
3 5

Salida de muestra
1
5
6
3
6

Ideas:

1. Primero use una matriz pre [], pre [i] representa el subíndice del número de repetición anterior del i-ésimo número en los datos de entrada. Si el i-ésimo número aparece por primera vez, entonces pre [i] = 0;

2. Utilice un mapa de mapeo map <long long, int>, que se utiliza para guardar la posición (subíndice) de la última aparición del valor de entrada actual y actualizar el pre;

3. La matriz de árbol msum se utiliza para almacenar los valores de suma que no se repiten en el intervalo, que inicialmente está vacío.

4. Desconecte todas las operaciones de consulta, ordene las operaciones de consulta de acuerdo con la r de todos los intervalos de preguntas (es decir, ordénelas en orden ascendente del extremo derecho de todos los intervalos de preguntas). Esto asegura que cuando un intervalo grande cubre un intervalo pequeño, no hay necesidad de volver a calcular la parte más pequeña.

5. De acuerdo con la cantidad de preguntas fuera de línea, agregue los datos de entrada uno por uno a la matriz del árbol (el número ingresado puede no necesariamente agregarse a la matriz del árbol al final para reducir cálculos innecesarios). Si el número agregado actualmente es ahora , su Este número se agregó antes, es decir, pre [ahora] no es 0, elimine el número agregado anteriormente y vuelva a agregar el número actual. Esto asegura que cada número repetido se actualizará uno tras otro después del intervalo, de modo que el intervalo tenga la propiedad de expansión hacia atrás.

6. En el proceso de sumar la matriz de árbol, cuando se alcanza el intervalo r del problema, la suma del intervalo se calcula una vez. Utilice la naturaleza de la matriz de árbol para calcular.

7. Guarde el orden de las respuestas en el orden de las preguntas y, finalmente, envíelas en consecuencia.

 

Código AC:

#include<cstdio> 
#include<cstring>
#include<map>
#include<algorithm>
using namespace std; 
typedef long long ll;
const int maxn = 3e5 + 5;
const int Q = 1e5 + 5;
map<ll ,int>mmp;
ll a[maxn], msum[maxn], ANS[maxn];
int pre[maxn], t, n, q;

struct Node{
	int l, r, id;
}node[Q];//离线问题

bool cmp(Node a, Node b){
	if(a.r == b.r){
		return a.l < b.l;
	}
	return a.r < b.r;
}

void update(int x, ll v){
	for(int i = x;i <= n;i += i & (-i)){
		msum[i] += v;
	}
}

ll getNum(int x){
	ll ans = 0;
	for(int i = x; i > 0;i -= i & (-i)){
		ans += msum[i];
	}
	return ans;
}
 
int main(){
	scanf("%d", &t);
	while(t--){
		memset(msum, 0 ,sizeof msum);
		memset(ANS, 0, sizeof ANS);
		memset(pre, 0, sizeof pre);
		mmp.clear();
		scanf("%d", &n);
		for(int i = 1;i <= n;i++){
			scanf("%lld", a + i);
			pre[i] = mmp[a[i]];
			mmp[a[i]] = i;//保存最后一次出现的位置 
		}
		scanf("%d", &q);
		for(int i = 1;i <= q;i++){
			scanf("%d%d", &node[i].l, &node[i].r);
			node[i].id = i;	//保存提问的顺序,从而保证输出的顺序!!!! 
		}
		sort(node + 1, node + q + 1, cmp);//按r的大小排序 
		int now = 1; //逐个加入 
		for(int i = 1; i <= q;i++){
			while(now <= node[i].r){
				if(pre[now]){
					update(pre[now], -a[now]);
				}
				update(now, a[now]);
				now++;
			}
			ANS[node[i].id] = getNum(node[i].r) - getNum(node[i].l - 1);
		}
		for(int i = 1;i <= q;i++){
			printf("%lld\n",ANS[i]);
		}
	}
	
	return 0;
}

 

Supongo que te gusta

Origin blog.csdn.net/qq_40596572/article/details/103995879
Recomendado
Clasificación