#include #include struct node { // Vrchol stromu struct node *left, *right; // Synové int id; // Číslo papíru int weight; // Velikost (váha) podstromu }; static int weight(struct node *n) { return (n ? n->weight : 0); // Váha stromu, prázdný má 0 } // Vytvoří ze stromu seznam, `right' ukazuje na následníka. struct node *tree_to_list(struct node *n, struct node *tail) { if (!n) return tail; n->right = tree_to_list(n->right, tail); return tree_to_list(n->left, n); } // Odpojí `count' prvků ze seznamu `*lp' a vytvoří z nich // vyvážený strom. Vrátí ukazatel na kořen. struct node *list_to_tree(struct node **lp, int count) { if (!count) return NULL; int half = (count-1)/2; struct node *left = list_to_tree(lp, half); struct node *root = *lp; *lp = root->right; root->left = left; root->right = list_to_tree(lp, count-1-half); root->weight = count; return root; } // Přepočítá váhy podle synů a pokud je strom příliš // vychýlený, přebuduje ho. struct node *reweight(struct node *n) { int lw = weight(n->left); int rw = weight(n->right); n->weight = 1 + lw + rw; if (lw+rw > 1 && (lw > 2*rw || rw > 2*lw)) { struct node *tmp = tree_to_list(n, NULL); n = list_to_tree(&tmp, n->weight); } return n; } // Vloží vrchol do stromu před všechny ostatní. struct node *add_start(struct node *root, struct node *new) { if (!root) { root = new; new->left = new->right = NULL; } else root->left = add_start(root->left, new); return reweight(root); } // Smaže k-tý nejmenší prvek ve stromu a vrátí jak tento // prvek (*kthp), tak nový kořen stromu. struct node *del_kth(struct node *n, int k, struct node **kthp) { if (k < weight(n->left)) { // k-tý nejmenší je v levém podstromu n->left = del_kth(n->left, k, kthp); return reweight(n); } k -= weight(n->left); if (k) { // k-tý nejmenší je v pravém podstromu n->right = del_kth(n->right, k-1, kthp); return reweight(n); } // Mám ho, pryč s ním. Má jen jednoho syna? *kthp = n; if (!n->left) return n->right; if (!n->right) return n->left; // Má dva => prohodím s maximem levého podstromu. n->left = del_kth(n->left, n->left->weight-1, kthp); int id = n->id; n->id = (*kthp)->id; (*kthp)->id = id; return reweight(n); } // Vypíše všechny hodnoty ve stromu. void dump_tree(FILE *fo, struct node *root) { if (!root) return; dump_tree(fo, root->left); fprintf(fo, "%d ", root->id); dump_tree(fo, root->right); } int main(void) { FILE *fi = fopen("papiry.in", "r"); FILE *fo = fopen("papiry.out", "w"); int N, K, op; fscanf(fi, "%d%d", &N, &K); // Vložíme všechna lejstra do stromu. struct node *root = NULL; for (int i=N; i>0; i--) { struct node *n = malloc(sizeof(*n)); n->id = i; root = add_start(root, n); } // Vykonáváme příkazy ze vstupu. for (int i=1; i<=K; i++) { fscanf(fi, "%d", &op); struct node *n; root = del_kth(root, op-1, &n); root = add_start(root, n); } // Vypíšeme, jak to dopadlo. dump_tree(fo, root); fputc('\n', fo); fclose(fo); fclose(fi); return 0; }