#include <stdio.h> #include <stdlib.h> #include <time.h> int cmp(const void *x, const void *y) { return *(int*)x - *(int*)y; } int main(int argc, char **argv) { srand(time(NULL)); int n = rand() % 1000 + 1; int m = rand() % 1000 + 1; if(argc >= 3) { n = atoi(argv[1]); m = atoi(argv[2]); } int k = argc == 4 ? atoi(argv[3]) : rand() % 100000 + 1; printf("%d %d\n", n, m); for(int i = 0; i < n; i++) { for(int j = 0; j < m - 1; j++) printf("%d ", rand() % 1000000000 + 1); printf("%d\n", rand() % 1000000000 + 1); } int *tab = calloc(k, sizeof(k)); for(int i = 0; i < k; i++) tab[i] = rand() % 1000000000 + 1; qsort(tab, k, sizeof(int), cmp); printf("%d\n", k); for(int i = 0; i < k - 1; i++) printf("%d ", tab[i]); printf("%d\n", tab[k - 1]); free(tab); return 0; }
0 oznacza brak poprawnej odpowiedzi na jakiś test
pierwsza kolumna to suma czasów
18292: Jak Tarn 19596: Mik Kali 19596: Paw Muri 21480: Pio Walk 21500: Pio Krze 23624: Sla Step 24212: Mar Ocze 27020: Pio Bzow 28296: Dam Rusa 28636: Kar Kona 28796: Dam Stra 29584: Pio Ryba 29612: Pio Gajo 30028: Mac Maty 30260: Mar Kola 30800: Mar Janu 34580: Paw Kacp 35160: Mic Karp 36428: Pio Posa 37112: Pio Rzep 37156: Krz Ziel 38996: Mic Soko 43140: Wik Jana 43616: Raf Kowa 49492: Dom Brul 53132: Paw Kali 0: Dam Piat 0: Dan Blas 0: Dom Rusa 0: Fil Slom 0: Kac Krol 0: Kon Wypy 0: Krz Nowi 0: Krz Parj 0: Luk Syno 0: Mac Maty (test) 0: Mac Pacu 0: Mac Wiec 0: Mag Sara 0: Mic Roza 0: Paw Kime 0: dzo busz (test)
/* 
 * Algorytm:
 * (a) wczytaj wszystkie pola do kolejki priorytetowej
 * (b) dopóki kolejka nie jest pusta
 *     (b1) zdejmij najwyższy element t
 *     (b2) sprawdź jego 4 sąsiadów. Jeżeli którykolwiek należy
 *          do jakiejś wyspy, dodaj t do tej wyspy. Jeżeli jest
 *          więcej niż 1 wyspa połącz te wyspy i dodaj do nich t.
 *          W przeciwnym przypadku stwórz jednoelementową wyspę.
 *     (b3) jeżeli szczyt kolejki priorytetowej jest niższy od t
 *          i kolejne zapytanie jest o wysokość t, wypisz ilość
 *          wysp.
 *
 * Wyspy są reprezentowane przez zbiory, dzięki czemu zapytania
 * o przynależność i łączenie wysp można wykonywać praktycznie
 * w czasie stałym.
 
 */
 
#include <stdio.h>
#include <alloca.h>
#include <stdlib.h>
 
#define READ_INT(a) a = 0; \
                    while ((ch = getchar_unlocked()) >= '0') \
                        a = a * 10 + (ch - '0');
char ch;
 
#define MAX_BOXEN (1024*1001)
#define MAX_QUESTIONS 100002
 
typedef struct Box {
    int height;
    short col;
    short row;
} Box;
 
#define coord(x,y) ((x)*1024+(y))
 
int BoxCmp(const void *x, const void *y)
    { return ((Box*)x)->height - ((Box*)y)->height; };
 
/* Union-Find */
int dad[MAX_BOXEN]; /*  0 - nie ma
                        1 - singleton
                        k - ma ojca k
                       -k - jest korzeniem rzędu k*/
 
int  Find   (int );
void Union  (int , int );
#define Insert(x)    (dad[x]=1)
#define SameSet(x,y) (Find(x)==(y))
 
int an_ind = 0; /* kolejne wolne pole; */
#define answers_push(x) (answers[an_ind++] = x)
#define answers_pop     (answers[--an_ind])
#define answers_empty   (an_ind == 0)
 
int qu_ind;
int qu_size;
#define questions_push(x) (questions[qu_ind--] = x)
#define questions_pop     (++qu_ind)
#define questions_top     (questions[qu_ind+1])
#define questions_empty   (qu_ind == qu_size)
 
int he_ind = 0;
#define heights_push(x) (heights[he_ind++]=x)
#define heights_pop     (heights[--he_ind])
#define heights_top     (heights[he_ind-1])
#define heights_empty   (he_ind == 0)
 
int main () {
 
setvbuf (stdout, NULL, _IOFBF, 2 << 5);
    short rows, // 1..1000
          cols; // 1..1000
 
    int islands = 0; // 0 .. 500000
 
    READ_INT (rows)
    READ_INT (cols)
 
    Box * heights = (Box *) alloca (sizeof (Box) * (cols*rows+1));
 
    Box b; // 1 .. 1 000 000 000
    for (b.row = 1; b.row <= rows; ++b.row)
    for (b.col = 1; b.col <= cols; ++b.col)
    {
        READ_INT (b.height)
        heights_push (b);
    }
 
    int nquestions; // 1 .. 100000
    READ_INT (nquestions)
 
    int * answers   = (int *)alloca(sizeof(int) * nquestions);
    int * questions = answers;
    qu_size = qu_ind = nquestions-1;
 
    qsort (heights, he_ind, sizeof (Box), BoxCmp);
 
    while (nquestions --> 0)
    {
        int q; // 1 .. 1 000 000 000
        READ_INT (q)
 
        if (q < heights_top.height)
            questions_push (q);
        else
        {
            do  /* każdego kolejnego dnia i tak wszystko będzie zalane */
                // scanf ("%d", & q);
                answers_push (0);
            while (nquestions --> 0);
            break;
        }
    }
 
    while (!heights_empty)
    {
        b = heights_pop;
 
        int o = coord (b.row,   b.col),
            n = coord (b.row-1, b.col),
            s = coord (b.row+1, b.col),
            e = coord (b.row,   b.col+1),
            w = coord (b.row,   b.col-1);
        int o1;
 
        Insert (o);
        islands++;
 
        /* dodaj/połącz wyspy */
        if ((b.row-1>0)     && (n = Find (n)))
            { Union (o,n); islands--; }
 
        if ((b.row+1<=rows) && (s = Find (s)) && ((o1 = Find(o)) != s))
            { Union (o1,s); islands--; }
 
        if ((b.col-1>0)     && (w = Find (w)) && ((o1 = Find(o)) != w))
            { Union (o1,w); islands--; }
 
        if ((b.col+1<=cols) && (e = Find (e)) && ((o1 = Find(o)) != e))
            { Union (o1,e); islands--; }
 
        /* kolejny/ostatni dzień */
        if (heights_empty || (heights_top.height != b.height))
        {
            /* dopóki nie wynurzą się kolejne pola */
            while (!questions_empty && questions_top >= heights_top.height)
            {
                questions_pop;
                answers_push (islands);
            }
            if (questions_empty) goto done;
        }
    }
 
done:
 
    /* już wszystko jest nad powierzchnią wody */
    while (!questions_empty)
    {
        questions_pop;
        answers_push (1);
    }
 
    unsigned len;
    char out[8];
    out[7] = '\0';
 
    if (!answers_empty) printf ("%d", answers_pop);
    while (!answers_empty)
    {
        int num = answers_pop;
 
        len = 6;
 
        do {
            out[len--] = (num % 10) + '0';
            num = num / 10;
        } while (num > 0);
 
        out[len] = ' ';
 
        fputs_unlocked (out + len, stdout);
    }
 
    return 0;
}
 
 
inline int Find (int  i)
{
    int root = i,
        temp;
 
    if (dad[i] == 0) return 0;  // nie ma
    else
    if (dad[i] == 1) return i;  // jest singletonem
 
    /* znajdź i - reprezentanta zbioru (zawsze ten sam) */
    while (dad[root] > 1)
        root = dad[root];
 
    /* Wszystkie odwiedzone wierzchołki mogą wskazywać na i */
    while (dad[i] > 1) {
        temp      = i;
        i         = dad[i];
        dad[temp] = root;
    }
 
    return root;
}
 
inline void Union (int i, int j)
{
    // assert (i != j)
 
    /* płytsze drzewo jest poddrzewem głębszego
     * mniejsze wartości dad[root] reprezentują głębsze drzewa.
     * -1 to korzeń */
 
    if (dad[j] > dad[i]) {
        dad[i] += -1 + dad[j];
        dad[j]  = i;
    } else {
        dad[j] += -1 + dad[i];
        dad[i]  = j;
    }
}