====== AISD: pracownia F ======
{{:aisd:2010_f.pdf|}}
===== Testy =====
#include
#include
#include
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;
}
===== Wyniki =====
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)
===== Rozwiązanie (2. czas) =====
/*
* 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
#include
#include
#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;
}
}