Фарбування корівника (срібло)#10345

Фарбування корівника (срібло) (Розбір)

Спочатку розглянемо одномірний варіант задачі. Нехай на числовій прямій задано відрізків [a_i, b_i], де 0 \le a_i, b_i \le 1000. Необхідно визначити, скількома відрізками покривається кожне ціле число на цій прямій.

Оголосимо цілочисельний масив , ініціалізуємо його нулями. Потім для кожного відрізка [a_i, b_i] виконаємо дві операції:

dp[a_i]++; dp[b_i + 1]--;

Далі обчислимо префіксні суми в масиві . Значення дорівнює кількості відрізків, що містять число .

Наприклад, нехай дано наступні відрізки: [3; 7], [6; 9], [1; 4], [3; 8], [2; 5]. Ініціалізуємо масив :

Для кожного відрізка [a_i, b_i] виконаємо дві операції: dp[a_i]++; dp[b_i + 1]--.

Тепер розглянемо двовимірний варіант задачі. На площині задано прямокутників з координатами (x_1, y_1) - (x_2, y_2)~(0 \le x_1, y_1, x_2, y_2 \le 1000). Потрібно визначити, скількома прямокутниками покривається кожна клітинка площини.

Оголосимо цілочисельний двовимірний масив , ініціалізуємо його нулями. Потім для кожного прямокутника (x_1, y_1) - (x_2, y_2) виконаємо чотири операції:

dp[x_1][y_1]++; dp[x_1][y_2 + 1]--; dp[x_2 + 1][y_1]--; dp[x_2 + 1][y_2 + 1]++;

Після цього обчислимо префіксні суми в масиві . Значення dp[i][j] буде дорівнювати числу прямокутників, що містять клітинку .

Розглянемо, наприклад, прямокутник (2, 2) - (4, 5).

Приклад

Розглянемо наведений приклад, що містить три прямокутники.

k = 2 шарами фарби покрито квадратів.

Реалізація алгоритму

Оголосимо двовимірний масив .

#define MAX 1001
int dp[MAX][MAX];

Читаємо вхідні дані.

scanf("%d %d", &n, &k);
while (n--)
{

Для кожного прямокутника (a, b) - (c, d) виконаємо чотири операції.

  scanf("%d %d %d %d", &a, &b, &c, &d);
  dp[a][b]++;
  dp[a][d]--;
  dp[c][b]--;
  dp[c][d]++;
}

В змінній підраховуємо кількість клітинок стіни, покритих рівно шарами фарби.

res = 0;

Обчислюємо префіксні суми в масиві .

for (i = 0; i < MAX; i++)
  for (j = 0; j < MAX; j++)
  {
    if (i) dp[i][j] += dp[i - 1][j];
    if (j) dp[i][j] += dp[i][j - 1];
    if (i && j) dp[i][j] -= dp[i - 1][j - 1];

Якщо клітинка покрита шарами фарби, то збільшуємо на ,

    if (dp[i][j] == k) res++;
  }

Виводимо відповідь.

printf("%d\n", res);