Cod sursa(job #2835636)

Utilizator ciprian.morosanuCiprian Morosanu ciprian.morosanu Data 18 ianuarie 2022 23:49:27
Problema Datorii Scor 0
Compilator c-64 Status done
Runda Arhiva de probleme Marime 2.95 kb
#include <stdio.h>
#include <stdlib.h>

typedef struct _Node {
    int leftValue;
    int rightValue;
    int sum;
    struct _Node *parent;
    struct _Node *left;
    struct _Node *right;
} Node;

typedef struct {
    Node *root;
    Node *leaves;
    int leavesCount;
} IntervalTree;

Node *node_new() {
    Node *node = malloc(1 * sizeof(Node));
    return node;
}

Node *intervalTree_generate(IntervalTree *tree, Node *parent, int leftValue, int rightValue) {
    if (leftValue == rightValue) {
        tree->leaves[leftValue].parent = parent;
        tree->leaves[leftValue].leftValue = leftValue;
        tree->leaves[leftValue].rightValue = leftValue;
        return &tree->leaves[leftValue];
    }
    Node *current = node_new();
    current->leftValue = leftValue;
    current->rightValue = rightValue;
    current->parent = parent;
    current->sum = 0;
    int mid = (leftValue + rightValue) / 2;
    current->left = intervalTree_generate(tree, current, leftValue, mid);
    current->right = intervalTree_generate(tree, current, mid + 1, rightValue);
    return current;
}

IntervalTree *intervalTree_new(int count) {
    IntervalTree *tree = malloc(1 * sizeof(IntervalTree));
    tree->leavesCount = count;
    tree->leaves = malloc((count + 1) * sizeof(Node));
    tree->root = intervalTree_generate(tree, NULL, 1, count);
    return tree;
}

//88ms without both
//130ms without update
//100ms without get
//50ms get 20ms update
void updateParents(Node *node, int delta) {
    Node *parent = node->parent;
    while (parent != NULL) {
        parent->sum += delta;
        parent = parent->parent;
    }
}

void update2(IntervalTree *tree, int day, int value) {
    tree->leaves[day].sum -= value;
    updateParents(tree->leaves + day, -value);
}

int get2(Node *node, int start, int end) {
    if (start == node->leftValue && end == node->rightValue) {
        return node->sum;
    }
    int nodeMid = (node->leftValue + node->rightValue) / 2;
    if (end <= nodeMid) {
        return get2(node->left, start, end);
    }
    if (start > nodeMid) {
        return get2(node->right, start, end);
    }
    return get2(node->left, start, nodeMid) + get2(node->right, nodeMid + 1, end);
}

int main() {
    char *inFileName = "datorii.in";
    char *outFileName = "datorii.out";
    FILE *in = fopen(inFileName, "r");
    if (in == NULL) {
        printf("Cannot open %s.\n", inFileName);
        return 1;
    }
    FILE *out = fopen(outFileName, "w");
    int n, m;
    fscanf(in, "%d %d", &n, &m);
    IntervalTree *tree = intervalTree_new(n);
    for (int i = 1; i <= n; ++i) {
        fscanf(in, "%d", &tree->leaves[i].sum);
        updateParents(tree->leaves + i, tree->leaves[i].sum);
    }
    for (int i = 0; i < m; ++i) {
        int op, num1, num2;
        fscanf(in, "%d %d %d", &op, &num1, &num2);
        if (op) {
            fprintf(out, "%d\n", get2(tree->root, num1, num2));
        } else {
            update2(tree, num1, num2);
        }
    }
    fclose(in);
    fclose(out);
    return 0;
}