#include #include #include #include void memerr() { fprintf(stderr, "Running out of memory!\n"); exit(1); } typedef enum {Black, White, Mixed} Nodetype; typedef struct Quadtree { unsigned int size; /* this quadtree covers 2^size x 2^size pixels */ Nodetype type; /* upper left, upper right, lower left, lower right */ struct Quadtree* trees[4]; } Quadtree; Quadtree* create_quadtree(unsigned int size) { Quadtree* root = malloc(sizeof(Quadtree)); if (!root) memerr(); *root = (Quadtree) {.size = size, .type = Black}; return root; } void delete_quadtree(Quadtree* qtree) { if (qtree->type == Mixed) { for (unsigned int k = 0; k < 4; ++k) { delete_quadtree(qtree->trees[k]); } } free(qtree); } #define SPLIT(i, i1, i2, size) \ (i1 = (i) >> ((size)-1), i2 = (i) & ~(1<<((size)-1))) void quadtree_put(Quadtree* qtree, unsigned int i, unsigned int j) { unsigned int sidelen = 1 << qtree->size; assert(i < sidelen && j < sidelen); if (sidelen == 1) qtree->type = White; /* trivial case */ if (qtree->type == White) return; /* nothing has to be done */ if (qtree->type != Mixed) { qtree->type = Mixed; for (unsigned int k = 0; k < 4; ++k) { qtree->trees[k] = create_quadtree(qtree->size - 1); } } unsigned int i1, i2, j1, j2; SPLIT(i, i1, i2, qtree->size); SPLIT(j, j1, j2, qtree->size); quadtree_put(qtree->trees[i1*2 + j1], i2, j2); /* check if all subtrees are of the same color */ Nodetype kind = Mixed; for (unsigned int k = 0; k < 4; ++k) { Nodetype subkind = qtree->trees[k]->type; if (subkind == Mixed) { kind = Mixed; break; } else if (kind == Mixed) { kind = subkind; } else if (kind != subkind) { kind = Mixed; break; } } /* our subtrees can be deleted */ if (kind != Mixed) { for (unsigned int k = 0; k < 4; ++k) { delete_quadtree(qtree->trees[k]); qtree->trees[k] = 0; } qtree->type = kind; } } void quadtree_print_line(Quadtree* qtree, unsigned int i) { unsigned int sidelen = 1 << qtree->size; assert(i < sidelen); if (qtree->type == Mixed) { unsigned int i1, i2; SPLIT(i, i1, i2, qtree->size); quadtree_print_line(qtree->trees[i1*2], i2); quadtree_print_line(qtree->trees[i1*2+1], i2); } else { char pixel = qtree->type == Black? '#': ' '; for (unsigned int k = 0; k < sidelen; ++k) { putchar(pixel); } } } void quadtree_print(Quadtree* qtree) { unsigned int sidelen = 1 << qtree->size; for (unsigned int i = 0; i < sidelen; ++i) { quadtree_print_line(qtree, i); putchar('\n'); } } void quadtree_string(Quadtree* qtree) { switch (qtree->type) { case Mixed: putchar('['); for (unsigned int k = 0; k < 4; ++k) { quadtree_string(qtree->trees[k]); } putchar(']'); break; case White: putchar('W'); break; case Black: putchar('B'); break; } } int main() { unsigned int sidelen; if (scanf("%u", &sidelen) != 1) { fprintf(stderr, "dimension expected\n"); exit(1); } if (sidelen == 0) { fprintf(stderr, "invalid dimension\n"); exit(1); } unsigned int size = 0; unsigned int l = sidelen; while (l >>= 1) { ++size; } Quadtree* qtree = create_quadtree(size); char command[8]; while (scanf("%7s", command) == 1) { if (strcmp(command, "PUT") == 0) { unsigned int i, j; if (scanf("%u %u", &i, &j) != 2) { fprintf(stderr, "parameters to PUT are missing\n"); exit(1); } if (i >= sidelen || j >= sidelen) { fprintf(stderr, "parameters to PUT are out of range\n"); exit(1); } quadtree_put(qtree, i, j); } else if (strcmp(command, "PRINT") == 0) { char param[8]; if (scanf("%7s", param) != 1) break; if (strcmp(param, "IMAGE") == 0) { quadtree_print(qtree); } else if (strcmp(param, "TREE") == 0) { quadtree_string(qtree); putchar('\n'); } else { fprintf(stderr, "invalid parameter to PRINT: %s\n", param); exit(1); } } else { fprintf(stderr, "unknown command: %s\n", command); exit(1); } } delete_quadtree(qtree); }