#include #include #include typedef struct { int odkud; int kam; } tchodnik; // Struktura na pamatování si vrcholů na obvodu záhonů. // Abychom nemuseli procházet každý vrchol (i ty, do kterých nevede žádný // chodník), tak si umí pamatovat intervaly vrcholů. typedef struct s_vrcholy tvrcholy; struct s_vrcholy { int start; int konec; bool virtualni_start; tvrcholy *dalsi; }; typedef struct s_zahon tzahon; struct s_zahon { int zacatek; int konec; int pocet; tvrcholy *vrcholy; tvrcholy *vrcholy_posledni; tzahon *dalsi; }; int chodnikcmp(const void *a,const void *b) { tchodnik *x = (tchodnik *) a; tchodnik *y = (tchodnik *) b; if (x->odkud == y->odkud) return y->kam - x->kam; // opačné pořadí else return x->odkud - y->odkud; } int N, K; tzahon *maximalni; tzahon *zahony; // Ukončení a započítání aktuálního úseku vrcholů na obvodu mnohoúhelníku void ukonci_usek(int konec) { int pocet_vrcholu = konec - zahony->vrcholy_posledni->start + 1; if (konec == N) pocet_vrcholu--; // První a poslední jsou totožné zahony->pocet += pocet_vrcholu; zahony->vrcholy_posledni->konec = konec; } // Ukončení záhonu, porovnání s maximem a případné zapamatování void ukonci_zahon() { ukonci_usek(zahony->konec); tzahon *dalsi = zahony->dalsi; // Pokud existuje další aktivní záhon, začni na něm opět počítat vrcholy if (dalsi != NULL) { tvrcholy *vrcholy = malloc(sizeof(tvrcholy)); vrcholy->start = zahony->konec; vrcholy->dalsi = NULL; vrcholy->virtualni_start = false; dalsi->vrcholy_posledni->dalsi = vrcholy; dalsi->vrcholy_posledni = vrcholy; } if (maximalni == NULL) maximalni = zahony; else if (maximalni->pocet < zahony->pocet) { free(maximalni); maximalni = zahony; } else free(zahony); zahony = dalsi; } void zpracuj_chodnik(int zacatek, int konec, bool virtualni_start) { // 1. Pokud existoval aktivní záhon, započítej úsek vrcholů a přeruš ho if (zahony != NULL) ukonci_usek(zacatek); // 2. Přidáme nový záhon vytvořený tímto chodníčkem tzahon *nova = malloc(sizeof(tzahon)); nova->zacatek = zacatek; nova->konec = konec; nova->pocet = 0; nova->dalsi = zahony; // Nový záhon obsahuje jeden nový úsek vrcholů nova->vrcholy = malloc(sizeof(tvrcholy)); nova->vrcholy->start = zacatek; nova->vrcholy->virtualni_start = virtualni_start; nova->vrcholy->dalsi = NULL; nova->vrcholy_posledni = nova->vrcholy; // Přidáme nový záhon do zásobníku záhonů zahony = nova; } int main(void) { // 1. Načtení vstupu scanf("%d %d", &N, &K); tchodnik *chodnik = malloc(sizeof(tchodnik) * K); for (int i = 0; i < K; i++) { scanf("%d %d", &chodnik[i].odkud, &chodnik[i].kam); if (chodnik[i].odkud > chodnik[i].kam) { int t = chodnik[i].odkud; chodnik[i].odkud = chodnik[i].kam; chodnik[i].kam = t; } } // 2. Seřadíme chodníky po obvodu mnohoúhelníku // (druhé souřadnice v reverzním pořadí) qsort(chodnik, K, sizeof(tchodnik), chodnikcmp); // HLAVNÍ ČÁST // Projdeme chodníky po obvodu a držíme si v zásobníku aktivní záhony, // každémz záhonu navíc počítáme počet vrcholů na obvodu (je rovný počtu // chodníků ohraničujících jej) a zapisujeme si tyto vrcholy // Začneme od vrcholu s indexem 0 a přidáme první záhon. Chceme, aby // skončil jako poslední, a proto mu konec nastavíme na poslední vrchol. zpracuj_chodnik(0, N, true); // Pak postupně skáčeme po nejbližších začátcích nebo koncích chodníků int pozice = 0; int index = 0; while (pozice != N) { // 1. Pokud tu nějaký záhon končí, zpracujeme konec if (zahony->konec == pozice) ukonci_zahon(); // 2. Zpracujeme všechny chodníky na aktuální pozici (pokud takové jsou) while (index < K && chodnik[index].odkud == pozice) { zpracuj_chodnik(pozice, chodnik[index].kam, false); index++; } // 3. Zvolíme si, kam skočit dál a skočíme if (index < K && zahony->konec > chodnik[index].odkud) pozice = chodnik[index].odkud; // začátek nového chodníku je blíž else pozice = zahony->konec; // konec je blíž } ukonci_zahon(); // Ukončení posledního záhonu // Vypsání maximálního záhonu printf("%d\n", maximalni->pocet); tvrcholy *aktualni = maximalni->vrcholy; int posledni = -1; while (aktualni != NULL) { if (aktualni->start != posledni && !aktualni->virtualni_start) { printf("%d ", aktualni->start); posledni = aktualni->start; } if (aktualni->konec != posledni && aktualni->konec != N) { printf("%d ", aktualni->konec); posledni = aktualni->konec; } aktualni = aktualni->dalsi; } printf("\n"); return 0; }