#include #include #define WINDOW_SIZE 10 /* * Circular buffer of nodes. Each node is in a double-linked list, ordered * by the node's value. */ struct node { struct node *next, *prev; int value; }; static struct node nodes[WINDOW_SIZE]; static struct node *head, *tail; static int oldest; /* * We start with all nodes initialized to zero (the exact value doesn't * matter, since all nodes' values will be set before any output), and * create our dlist. */ static void init() { int i; oldest = 0; for (i = 0; i < WINDOW_SIZE; i++) { nodes[i].prev = nodes + i - 1; nodes[i].next = nodes + i + 1; nodes[i].value = 0; } nodes[0].prev = nodes[WINDOW_SIZE - 1].next = NULL; head = nodes; tail = nodes + WINDOW_SIZE - 1; } /* * Add the specified value to the queue, knocking the oldest entry out. * Return the median value (specifically the (WINDOW_SIZE/2)-th value) of * the set. */ static int add(int value) { struct node *o, *n; int i, ret; enum { ADD = (1 << 0), RET = (1 << 1) } todo; /* Pick the oldest node */ o = nodes + oldest; if (++oldest == WINDOW_SIZE) oldest = 0; /* Remove it from the dlist */ if (o->prev) o->prev->next = o->next; else head = o->next; if (o->next) o->next->prev = o->prev; else tail = o->prev; o->value = value; /* Loop until we've both added the new node and got a return value */ todo = ADD | RET; for ( n = head, i = 0; todo && n; n = n->next, i++ ) { /* Add the new node here if subsequent nodes are too large */ if (todo & ADD && n->value >= value) { o->prev = n->prev; if (o->prev) o->prev->next = o; else head = o; o->next = n; n->prev = o; n = o; todo &= ~ADD; } /* Save the return value if this is the (WINDOW_SIZE/2)-th node */ if (i == WINDOW_SIZE / 2) { ret = n->value; todo &= ~RET; } } /* If we haven't yet added the node, add it to the tail */ if (todo & ADD) { o->prev = tail; tail->next = o; o->next = NULL; tail = o; } if (todo & RET) ret = tail->value; /* Should never be reached */ return ret; } int main(int argc, char **argv) { int value, i; /* Prep our nodes */ init(); /* * At least WINDOW_SIZE input values are required before an output value * is produced. */ i = WINDOW_SIZE - 1; while (scanf("%d", &value) == 1) { if (i) { add(value); i--; } else printf("%d\n", add(value)); } return 0; }