/* * Author: Titouan Rigoudy */ #include #include #include #include "segtree.h" // Allocate new segment tree spanning the [i, j[ interval with value v struct segtree *segtree_new(int i, int j, long v) { if (i < 0 || j <= i) { return NULL; } struct segtree *st = malloc(sizeof *st); if (!st) { return NULL; } st->i = i; st->j = j; st->v = v; st->left = NULL; st->right = NULL; return st; } struct segtree *segtree_new_simple(int n) { int x; for (x = 1; x < n; x *= 2) {} return segtree_new(0, x, 0); } // Free segment tree data structure void segtree_free(struct segtree *st) { if (!st) { return; } segtree_free(st->left); segtree_free(st->right); free(st); } void segtree_print_prefix(struct segtree *st, char *prefix) { if (!st) { printf("%sNULL\n", prefix); } printf("%ssegtree{i: %d, j: %d, v: %ld}\n", prefix, st->i, st->j, st->v); int n = strlen(prefix); char *newprefix = malloc((n+3) * sizeof(*newprefix)); snprintf(newprefix, n+3, "%s ", prefix); if (st->left) { segtree_print_prefix(st->left, newprefix); } if (st->right) { segtree_print_prefix(st->right, newprefix); } free(newprefix); } // Rudimentary debug printing void segtree_print(struct segtree *st) { segtree_print_prefix(st, ""); } // Add v to the [i, j[ interval in the segment tree st void segtree_add(struct segtree *st, int i, int j, long v) { if (!st) { fprintf(stderr, "Trying to add to null segtree\n"); return; } if (i < st->i || j > st->j) { fprintf(stderr, "Trying to add out of bounds of segtree\n"); return; } if (i == st->i && j == st->j) { st->v += v; return; } int mid = (st->i + st->j) / 2; if (!st->left) { st->left = segtree_new(st->i, mid, 0); } if (j <= mid) { segtree_add(st->left, i, j, v); return; } if (!st->right) { st->right = segtree_new(mid, st->j, 0); } if (i >= mid) { segtree_add(st->right, i, j, v); return; } // i < mid && j > mid segtree_add(st->left, i, mid, v); segtree_add(st->right, mid, j, v); } // Get the value of element i in the segment tree st long segtree_get(struct segtree *st, int i) { if (!st) { fprintf(stderr, "Trying to get value of null segtree\n"); return 0; } if (i < st->i || i >= st->j) { fprintf(stderr, "Trying to get value out of segtree bounds\n"); return 0; } if (st->i == i && st->j == i) { return st->v; } int mid = (st->i + st->j) / 2; if (i < mid && st->left) { return st->v + segtree_get(st->left, i); } if (i >= mid && st->right) { return st->v + segtree_get(st->right, i); } return st->v; // All descendant values are zero }