¿Cuál es el algoritmo para resolver el problema BRCKTS de SPOJ?

Este problema es una de las mejores aplicaciones de los árboles de segmentos.
Intente comprender los árboles de segmentos y sus ventajas a partir de las siguientes fuentes
Árbol de segmentos | Conjunto 1 (Suma del rango dado) – GeeksforGeeks
Tutoriales de algoritmos

Construya un árbol de segmentos para la expresión de paréntesis dada. Para construir, puede usar una representación entera para ‘(‘ y ‘)’, digamos +1 o -1. En cada nodo del almacén del árbol, la suma de sus hijos y un valor que identifica de forma única
El par “()” en sus nodos secundarios (esta es la captura).
¿Ahora lo que necesita en el nodo raíz para las expresiones de paréntesis correctas?
Necesitas dos cosas:

1. La suma de todos los nodos hoja es cero
2. El segundo valor también debe ser cero.

Ahora, en caso de reemplazo o actualización, puede aprovechar la eficiencia de los árboles de segmentos. Actualice solo aquellos nodos, que contienen el índice del corchete actualizado.
Como estamos usando una representación entera, reemplácela en consecuencia
(->) entonces +1 ——> -1
) -> (entonces -1 ——> +1
Y nuevamente calcule, la suma y el segundo valor para todo el árbol, ya que cambiará.

¡Todo lo mejor!

Puede que no sea la persona adecuada para responder a este problema en este momento porque todavía no lo he resuelto, pero tengo la sensación de que este problema tomará complejidad O (n + mlogn). Estoy preparado con un algoritmo que se puede usar para actualizar la cadena de manera ascendente utilizando la complejidad O (logn).
Digamos que tienes una expresión con N caracteres. Luego haz un árbol con N nodos en el nivel más bajo. Cada nodo representa un personaje. Entonces el nivel superior tendrá nodos de techo (N / 2). Cada nodo en este nivel representa la concatenación de dos nodos del nivel inferior. Sigue haciendolo. El nivel superior tendrá 1 nodo que representa la cadena completa que se le ha dado.
(()) () ((- Nivel 4 (1 nodo)
(()) () ((- Nivel 3 (2 nodos)
(()) () ((- Nivel 2 (4 nodos)
(()) () ((- Nivel 1 (8 nodos)
Ahora cada nodo almacena dos valores, el no. de llaves de apertura requeridas a su izquierda y el no. de cerrar llaves requeridas a su derecha para hacer que la expresión representada por ella sea una expresión válida. Es trivial para los nodos más inferiores. Es (0,1) para una llave de apertura y (1,0) para una llave de cierre. ¡Ahora descubra cómo usará estos valores para encontrar valores en los niveles superiores! Y luego descubra cómo puede actualizar este árbol en O (log n). La operación de verificación es trivial: la cadena es una expresión válida si el valor en el nodo raíz es (0,0).
Espero que entiendas lo que quiero decir aquí, si en cualquier caso tienes alguna duda sobre este problema, házmelo saber, pero primero pruébalo tú mismo. ¡Espero que esto funcione!

Cada segmento (nodo) debe tener dos campos:

  1. Número de paréntesis abiertos no coincidentes en este segmento
  2. Número de paréntesis cerrados no coincidentes en este segmento

Estos dos campos son suficientes para fusionar segmentos y decidir si un segmento es o no un paréntesis correcto.

He explicado los árboles de segmentos con soluciones para este problema y varios otros aquí: un enfoque simple para segmentar árboles

Se puede resolver usando el árbol de segmentos o BIT. Aquí hay algunos tutoriales:
Permítanos codificar: Segmentar árboles
MAXimal :: algo :: Дерево отрезков

¡Feliz codificación!