#include #include // struktura pro kandidáta na nejvyšší číslo typedef struct kandidat { int hodnota; int pozice; struct kandidat *dalsi, *predchozi; // obousměrný spojový seznam } Kandidat; int R, S, r, s; // vstupní parametry int **vstup; // vstupní tabulka int **vystup; // výtupnní tabulka Kandidat **kandidati; // seznam prvních kandidátů pro jednotlivé řádky Kandidat **posl; // seznam posledních kandidátů pro jednotlivé řádky int *sloupec; // aktuální maxima řádkových úseků Kandidat *slKandidat = NULL; // spojový seznam kandidátů ve sloupci Kandidat *poslSlKand = NULL; // poslední sloupcový kandidát void posunRadkovychKandidatu(int i, int j) { // vytvoř kandidáta pro nové číslo Kandidat *k = (Kandidat *)malloc(sizeof(Kandidat)); k->hodnota = vstup[i][j]; k->pozice = j; k->dalsi = NULL; k->predchozi = NULL; // maž od konce kandidáty menší nebo stejně velké než nový kandidát Kandidat *akt = posl[i]; while (akt != NULL && akt->hodnota <= k->hodnota) { Kandidat *p = akt->predchozi; free(akt); akt = p; } posl[i] = k; // nové číslo přijde na konec if (akt != NULL) { akt->dalsi = k; k->predchozi = akt; } else { kandidati[i] = k; // nové číslo je první kandidát } } void posunSloupcovychKandidatu(int i) { // vytvoř kandidáta pro nové číslo Kandidat *k = (Kandidat *)malloc(sizeof(Kandidat)); k->hodnota = sloupec[i]; k->pozice = i; k->dalsi = NULL; k->predchozi = NULL; // maž od konce kandidáty menší nebo stejně velké než nový kandidát Kandidat *akt = poslSlKand; while (akt != NULL && akt->hodnota <= k->hodnota) { Kandidat *p = akt->predchozi; free(akt); akt = p; } poslSlKand = k; // nové číslo přijde na konec if (akt != NULL) { akt->dalsi = k; k->predchozi = akt; } else { slKandidat = k; // nové číslo je první kandidát } } int main(void) { scanf("%d%d%d%d", &R, &S, &r, &s); // parametry vstupu // alokace pamětí pro pole vstup = (int **)malloc(sizeof(int *) * R); vystup = (int **)malloc(sizeof(int *) * (R - r + 1)); kandidati = (Kandidat **)malloc(sizeof(Kandidat *) * R); posl = (Kandidat **)malloc(sizeof(Kandidat *) * R); sloupec = (int *)malloc(sizeof(int) * R); // načti vstupní tabulku int a; for (int i = 0; i < R; i++) { vstup[i] = (int *)malloc(sizeof(int) * S); vystup[i] = (int *)malloc(sizeof(int) * (S - s + 1)); for (int j = 0; j < S; j++) { scanf("%d", &a); vstup[i][j] = a; } } // inicializace prvních úseků řádků for (int i = 0; i < R; i++) { for (int j = 0; j < s; j++) { posunRadkovychKandidatu(i, j); } } // pro každý sloupec výsledné tabulky for (int j = s; j <= S; j++) { // maxima v sloupci úseků for (int i = 0; i < R; i++) { sloupec[i] = kandidati[i]->hodnota; } // vyhodnoť sloupec // inicializace seznamu kandidátů z prvního úseku slKandidat = NULL; poslSlKand = NULL; for (int i = 0; i < r; i++) { posunSloupcovychKandidatu(i); } vystup[0][j - s] = slKandidat->hodnota; // posouvání maxim ve sloupci for (int i = r; i < R; i++) { // nové číslo přijde na konec posunSloupcovychKandidatu(i); // pokud první číslo vypadlo z úseku, smaž ho if (slKandidat->pozice == i - r) { Kandidat *akt = slKandidat->dalsi; akt->predchozi = NULL; free(slKandidat); slKandidat = akt; } vystup[i - r + 1][j - s] = slKandidat->hodnota; } // posunutí řádkových úseků if (j < S) { for (int i = 0; i < R; i++) { posunRadkovychKandidatu(i, j); // pokud první číslo vypadlo z úseku, smaž ho if (kandidati[i]->pozice == j - s) { Kandidat *akt = kandidati[i]; kandidati[i] = kandidati[i]->dalsi; kandidati[i]->predchozi = NULL; free(akt); akt = NULL; } } } } // vypiš výslednou tabulku for (int i = 0; i < R - r + 1; i++) { for (int j = 0; j < S - s + 1; j++) { printf("%d ", vystup[i][j]); } printf("\n"); } return 0; }