Tövlənin boyanması (gümüş)#10345

Tövlənin boyanması (gümüş) (Həll təhlili)

Əvvəlcə məsələnin bir ölçülü variantını nəzərdən keçirək. Tutaq ki, say xəttinin üzərində intervalı [a_i, b_i] verilmişdir, harada 0 \le a_i, b_i \le 1000. Bu xəttin üzərində hər bir tam ədədin neçə intervalla əhatə olunduğunu müəyyən etmək lazımdır.

Tam ədədli massivini elan edirik və onu sıfırlarla başladırırıq. Sonra hər bir interval üçün [a_i, b_i] iki əməliyyat yerinə yetiririk:

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

Daha sonra massivində prefiks cəmlərini hesablayırıq. qiyməti ədədini əhatə edən intervaların sayına bərabərdir.

Məsələn, aşağıdakı intervallar verilmişdir: [3; 7], [6; 9], [1; 4], [3; 8], [2; 5]. massivini başladırırıq:

Hər bir interval üçün [a_i, b_i] iki əməliyyat yerinə yetiririk: dp[a_i]++; dp[b_i + 1]--.

İndi məsələnin iki ölçülü variantını nəzərdən keçirək. Məsahə düzbucaqlının (x_1, y_1) - (x_2, y_2)~(0 \le x_1, y_1, x_2, y_2 \le 1000) koordinatları ilə verilir. Hər bir yerin neçə düzbucaqlı ilə əhatə olunduğunu müəyyən etmək lazımdır.

Tam ədədli iki ölçülü massivini elan edirik və onu sıfırlarla başladırırıq. Sonra hər bir düzbucaqlı üçün (x_1, y_1) - (x_2, y_2) dörd əməliyyat yerinə yetiririk:

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

Bundan sonra massivində prefiks cəmlərini hesablayırıq. dp[i][j] qiyməti yerini əhatə edən düzbucaqlıların sayına bərabər olacaq.

Məsələn, (2, 2) - (4, 5) düzbucaqlı nümunəsini nəzərdən keçirək.

Nümunə

Üç düzbucaqlı ehtiva edən verilmiş nümunəni nəzərdən keçirək.

k = 2 təbəqə ilə boyanmış kvadrat var.

Alqoritmin həyata keçirilməsi

İki ölçülü massivini elan edirik.

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

Giriş məlumatlarını oxuyuruq.

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

Hər bir düzbucaqlı üçün (a, b) - (c, d) dörd əməliyyat yerinə yetiririk.

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

təbəqə ilə boyanmış divar hüceyrələrinin sayını dəyişənində hesablayırıq.

res = 0;

massivində prefiks cəmlərini hesablayırıq.

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];

Əgər hüceyrəsi təbəqə ilə boyanıbsa, 1 artırılır,

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

Cavabı çıxarırıq.

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