Cod sursa(job #3137078)

Utilizator alvaro.regueira-vilarAlvaro Regueira Vilar alvaro.regueira-vilar Data 11 iunie 2023 10:37:10
Problema Arbori de intervale Scor 100
Compilator c-64 Status done
Runda Arhiva educationala Marime 3.75 kb
#include <stdio.h>
#include <stdlib.h>

struct IntervalNode {
    int low;
    int high;
    int max;
    struct IntervalNode* left;
    struct IntervalNode* right;
};

// Crea un nuevo nodo del árbol de intervalo con los límites especificados
struct IntervalNode* newNode(int low, int high) {
    struct IntervalNode* node = (struct IntervalNode*)malloc(sizeof(struct IntervalNode));
    node->low = low;
    node->high = high;
    node->max = 0;
    node->left = NULL;
    node->right = NULL;
    return node;
}

// Construye el árbol de intervalo recursivamente
struct IntervalNode* buildIntervalTree(int arr[], int start, int end) {
    if (start > end) {
        return NULL;
    }

    struct IntervalNode* root = newNode(start, end);

    if (start == end) {
        root->max = arr[start];
        return root;
    }

    int mid = (start + end) / 2;

    // Construye los hijos izquierdo y derecho
    struct IntervalNode* leftChild = buildIntervalTree(arr, start, mid);
    struct IntervalNode* rightChild = buildIntervalTree(arr, mid + 1, end);

    root->left = leftChild;
    root->right = rightChild;
    root->max = (leftChild->max > rightChild->max) ? leftChild->max : rightChild->max;

    return root;
}

// Realiza una consulta de máximo en el árbol de intervalo
int queryMax(struct IntervalNode* root, int start, int end) {
    if (root == NULL || end < root->low || start > root->high) {
        return 0;
    }

    if (start <= root->low && end >= root->high) {
        return root->max;
    }

    // Realiza una búsqueda recursiva en los hijos izquierdo y derecho
    int leftMax = queryMax(root->left, start, end);
    int rightMax = queryMax(root->right, start, end);

    return (leftMax > rightMax) ? leftMax : rightMax;
}

// Actualiza el valor de un elemento en el árbol de intervalo
void updateElement(struct IntervalNode* root, int index, int newValue) {
    if (root == NULL || index < root->low || index > root->high) {
        return;
    }

    if (root->low == root->high && root->low == index) {
        root->max = newValue;
        return;
    }

    // Realiza una búsqueda recursiva para encontrar el nodo correspondiente al índice y actualiza su valor
    updateElement(root->left, index, newValue);
    updateElement(root->right, index, newValue);

    root->max = (root->left->max > root->right->max) ? root->left->max : root->right->max;
}

int main() {
    int N, M;
    FILE *inputFile;
    FILE *outputFile;

    // Abre el archivo de entrada en modo lectura y el archivo de salida en modo escritura
    inputFile = fopen("arbint.in", "r");
    outputFile = fopen("arbint.out", "w");

    // Lee el tamaño del vector N y el número de operaciones M desde el archivo de entrada
    fscanf(inputFile, "%d %d", &N, &M);

    int arr[N];
    // Lee los elementos del vector desde el archivo de entrada
    for (int i = 0; i < N; i++) {
        fscanf(inputFile, "%d", &arr[i]);
    }

    // Construye el árbol de intervalo
    struct IntervalNode* root = buildIntervalTree(arr, 0, N - 1);

    // Procesa las operaciones
    for (int i = 0; i < M; i++) {
        int op, a, b;
        fscanf(inputFile, "%d %d %d", &op, &a, &b);

        if (op == 0) {
            // Realiza una consulta de máximo en el intervalo [a, b]
            int maxVal = queryMax(root, a - 1, b - 1);
            // Escribe el resultado en el archivo de salida
            fprintf(outputFile, "%d\n", maxVal);
        } else if (op == 1) {
            // Actualiza el elemento en la posición a con el valor b
            updateElement(root, a - 1, b);
        }
    }

    // Cierra los archivos de entrada y salida
    fclose(inputFile);
    fclose(outputFile);

    return 0;
}